[_stream_ttl_stepper setEnabled:NO];
[_stream_port_lbl setStringValue:_NS("Port")];
[_stream_sap_ckb setStringValue:_NS("SAP Announcement")];
- [_stream_http_ckb setStringValue:_NS("HTTP Announcement")];
- [_stream_rtsp_ckb setStringValue:_NS("RTSP Announcement")];
- [_stream_sdp_ckb setStringValue:_NS("Export SDP as file")];
+ [[_stream_sdp_matrix cellWithTag:0] setTitle:_NS("None")];
+ [[_stream_sdp_matrix cellWithTag:1] setTitle:_NS("HTTP Announcement")];
+ [[_stream_sdp_matrix cellWithTag:2] setTitle:_NS("RTSP Announcement")];
+ [[_stream_sdp_matrix cellWithTag:3] setTitle:_NS("Export SDP as file")];
[_stream_sap_ckb setState:NSOffState];
- [_stream_http_ckb setState:NSOffState];
- [_stream_rtsp_ckb setState:NSOffState];
- [_stream_sdp_ckb setState:NSOffState];
+ [_stream_sdp_matrix setEnabled:NO];
/* there is no way to hide single cells, so replace the existing ones with empty cells.. */
id blankCell = [[[NSCell alloc] init] autorelease];
- (IBAction)finalizePanel:(id)sender
{
+ if (b_streaming) {
+ if ([[[_stream_type_pop selectedItem] title] isEqualToString:@"HTTP"]) {
+ NSString *muxformat = [self.currentProfile objectAtIndex:0];
+ if ([muxformat isEqualToString:@"wav"] || [muxformat isEqualToString:@"mov"] || [muxformat isEqualToString:@"mp4"] || [muxformat isEqualToString:@"mkv"]) {
+ NSBeginInformationalAlertSheet(_NS("Invalid container format for HTTP streaming"), _NS("OK"), @"", @"", _window,
+ nil, nil, nil, nil, @"%@",
+ _NS("Media encapsulated as %@ cannot be streamed through the HTTP protocol for technical reasons."),
+ [[self currentEncapsulationFormatAsFileExtension:YES] uppercaseString]);
+ return;
+ }
+ }
+ }
+
playlist_t * p_playlist = pl_Get(VLCIntf);
input_item_t *p_input = input_item_New([_MRL UTF8String], [[_dropin_media_lbl stringValue] UTF8String]);
return;
input_item_AddOption(p_input, [[self composedOptions] UTF8String], VLC_INPUT_OPTION_TRUSTED);
+ if (b_streaming)
+ input_item_AddOption(p_input, [[NSString stringWithFormat:@"ttl=%@", [_stream_ttl_fld stringValue]] UTF8String], VLC_INPUT_OPTION_TRUSTED);
int returnValue;
returnValue = playlist_AddInput(p_playlist, p_input, PLAYLIST_STOP, PLAYLIST_END, true, pl_Unlocked);
- (IBAction)closeStreamPanel:(id)sender
{
- NSMutableString * labelContent = [[NSMutableString alloc] initWithFormat:@"%@ @ %@:%@", [_stream_type_pop titleOfSelectedItem], [_stream_address_fld stringValue], [_stream_port_fld stringValue]];
-
- if ([_stream_type_pop indexOfSelectedItem] > 1) {
- [labelContent appendFormat:@" TTL:%@", [_stream_ttl_fld stringValue]];
- if ([_stream_sap_ckb state] || [_stream_rtsp_ckb state] || [_stream_http_ckb state] || [_stream_sdp_ckb state])
- [labelContent appendFormat:@" — %@:\"%@\" (", _NS("Channel"), [_stream_channel_fld stringValue]];
+ /* provide a summary of the user selections */
+ NSMutableString * labelContent = [[NSMutableString alloc] initWithFormat:_NS("%@ stream to %@:%@"), [_stream_type_pop titleOfSelectedItem], [_stream_address_fld stringValue], [_stream_port_fld stringValue]];
- BOOL b_gotSomething;
- if (_stream_sap_ckb) {
- [labelContent appendString:@"SAP"];
- b_gotSomething = YES;
- }
- if (_stream_rtsp_ckb) {
- if (b_gotSomething)
- [labelContent appendString:@", "];
- [labelContent appendString:@"RTSP"];
- b_gotSomething = YES;
- }
- if (_stream_http_ckb) {
- if (b_gotSomething)
- [labelContent appendString:@", "];
- [labelContent appendString:@"HTTP"];
- b_gotSomething = YES;
- }
- if ([_stream_sdp_ckb state]) {
- if (b_gotSomething)
- [labelContent appendString:@", "];
- [labelContent appendString:@"SDP"];
- }
+ if ([_stream_type_pop indexOfSelectedItem] > 1)
+ [labelContent appendFormat:@" (\"%@\")", [_stream_channel_fld stringValue]];
- if ([_stream_sap_ckb state] || [_stream_rtsp_ckb state] || [_stream_http_ckb state] || [_stream_sdp_ckb state])
- [labelContent appendString:@")"];
- }
[_destination_stream_lbl setStringValue:labelContent];
[labelContent release];
+ /* catch obvious errors */
+ if (![[_stream_address_fld stringValue] length] > 0) {
+ NSBeginInformationalAlertSheet(_NS("No Address given"),
+ _NS("OK"), @"", @"", _stream_panel, nil, nil, nil, nil,
+ @"%@", _NS("In order to stream, a valid destination address is required."));
+ return;
+ }
+
+ if ([_stream_sap_ckb state] && ![[_stream_channel_fld stringValue] length] > 0) {
+ NSBeginInformationalAlertSheet(_NS("No Channel Name given"),
+ _NS("OK"), @"", @"", _stream_panel, nil, nil, nil, nil,
+ @"%@", _NS("SAP stream announcement is enabled. However, no channel name is provided."));
+ return;
+ }
+
+ if ([_stream_sdp_matrix isEnabled] && [_stream_sdp_matrix selectedCell] != [_stream_sdp_matrix cellWithTag:0] && ![[_stream_sdp_fld stringValue] length] > 0) {
+ NSBeginInformationalAlertSheet(_NS("No SDP URL given"),
+ _NS("OK"), @"", @"", _stream_panel, nil, nil, nil, nil,
+ @"%@", _NS("A SDP export is requested, but no URL is provided."));
+ return;
+ }
+
+ /* store destination for further reference and update UI */
+ [self setOutputDestination: [_stream_address_fld stringValue]];
+ [self updateOKButton];
+
[_stream_panel orderOut:sender];
[NSApp endSheet: _stream_panel];
}
[_stream_ttl_fld setEnabled:NO];
[_stream_ttl_stepper setEnabled:NO];
[_stream_sap_ckb setEnabled:NO];
- [_stream_rtsp_ckb setEnabled:NO];
- [_stream_http_ckb setEnabled:NO];
- [_stream_sdp_ckb setEnabled:NO];
+ [_stream_sdp_matrix setEnabled:NO];
} else if (index == 2) { // RTP
[_stream_ttl_fld setEnabled:YES];
[_stream_ttl_stepper setEnabled:YES];
[_stream_sap_ckb setEnabled:YES];
- [_stream_rtsp_ckb setEnabled:YES];
- [_stream_http_ckb setEnabled:YES];
- [_stream_sdp_ckb setEnabled:YES];
- [_stream_channel_fld setEnabled:YES];
- [_stream_sdp_fld setEnabled:[_stream_sdp_ckb state]];
+ [_stream_sdp_matrix setEnabled:YES];
} else { // UDP
[_stream_ttl_fld setEnabled:YES];
[_stream_ttl_stepper setEnabled:YES];
[_stream_sap_ckb setEnabled:YES];
- [_stream_rtsp_ckb setEnabled:NO];
- [_stream_http_ckb setEnabled:NO];
- [_stream_sdp_ckb setEnabled:NO];
- [_stream_channel_fld setEnabled:YES];
+ [_stream_sdp_matrix setEnabled:NO];
}
+ [self streamAnnouncementToggle:sender];
}
- (IBAction)streamAnnouncementToggle:(id)sender
{
- [_stream_sdp_fld setEnabled:[_stream_sdp_ckb state]];
+ [_stream_channel_fld setEnabled:[_stream_sap_ckb state] && [_stream_sap_ckb isEnabled]];
+ [_stream_sdp_fld setEnabled:[_stream_sdp_matrix isEnabled] && ([_stream_sdp_matrix selectedCell] != [_stream_sdp_matrix cellWithTag:0])];
+
+ if ([[_stream_sdp_matrix selectedCell] tag] == 3)
+ [_stream_sdp_browsefile_btn setEnabled: YES];
+ else
+ [_stream_sdp_browsefile_btn setEnabled: NO];
+}
+
+- (IBAction)sdpFileLocationSelector:(id)sender
+{
+ NSSavePanel * saveFilePanel = [NSSavePanel savePanel];
+ [saveFilePanel setCanSelectHiddenExtension: YES];
+ [saveFilePanel setCanCreateDirectories: YES];
+ [saveFilePanel setAllowedFileTypes:[NSArray arrayWithObject:@"sdp"]];
+ [saveFilePanel beginSheetModalForWindow:_stream_panel completionHandler:^(NSInteger returnCode) {
+ if (returnCode == NSOKButton)
+ [_stream_sdp_fld setStringValue:[[saveFilePanel URL] path]];
+ }];
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
[composedOptions appendFormat:@",soverlay"];
}
- // add muxer
- [composedOptions appendFormat:@"}:standard{mux=%@", [self.currentProfile objectAtIndex:0]];
+ if (!b_streaming) {
+ /* file transcoding */
+ // add muxer
+ [composedOptions appendFormat:@"}:standard{mux=%@", [self.currentProfile objectAtIndex:0]];
+
+ // add output destination
+ [composedOptions appendFormat:@",dst=%@,access=file}", _outputDestination];
+ } else {
+ /* streaming */
+ if ([[[_stream_type_pop selectedItem] title] isEqualToString:@"RTP"])
+ [composedOptions appendFormat:@":rtp{mux=ts,dst=%@,port=%@", _outputDestination, [_stream_port_fld stringValue]];
+ else if ([[[_stream_type_pop selectedItem] title] isEqualToString:@"UDP"])
+ [composedOptions appendFormat:@":standard{mux=ts,dst=%@,port=%@,access=udp", _outputDestination, [_stream_port_fld stringValue]];
+ else if ([[[_stream_type_pop selectedItem] title] isEqualToString:@"MMSH"])
+ [composedOptions appendFormat:@":standard{mux=asfh,dst=%@,port=%@,access=mmsh", _outputDestination, [_stream_port_fld stringValue]];
+ else
+ [composedOptions appendFormat:@":standard{mux=%@,dst=%@,port=%@,access=http", [self.currentProfile objectAtIndex:0], [_stream_port_fld stringValue], _outputDestination];
+
+ if ([_stream_sap_ckb state])
+ [composedOptions appendFormat:@",sap,name=\"%@\"", [_stream_channel_fld stringValue]];
+ if ([_stream_sdp_matrix selectedCell] != [_stream_sdp_matrix cellWithTag:0]) {
+ NSInteger tag = [[_stream_sdp_matrix selectedCell] tag];
+ switch (tag) {
+ case 1:
+ [composedOptions appendFormat:@",sdp=\"http://%@\"", [_stream_sdp_fld stringValue]];
+ break;
+ case 2:
+ [composedOptions appendFormat:@",sdp=\"rtsp://%@\"", [_stream_sdp_fld stringValue]];
+ break;
+ case 3:
+ [composedOptions appendFormat:@",sdp=\"file://%s\"", vlc_path2uri([[_stream_sdp_fld stringValue] UTF8String], NULL)];
+ default:
+ break;
+ }
+ }
- // add output destination (file only at this point)
- [composedOptions appendFormat:@",dst=%@,access=file}", _outputDestination];
+ [composedOptions appendString:@"} :sout-keep"];
+ }
NSString * returnString = [NSString stringWithString:composedOptions];
[composedOptions release];