I'm using Xamarin Android to develop an app for song suggestions and I am using embeded youtube url, and the thing I'm trying to understand is why some videos are playing fine and other are showing error and not playing at all. The error is 'Video Unavailable'.
I found a solution that said to upload the html to a server, but I can't upload it because I change the video dynamically
Thanks.
protected async override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Window.RequestFeature(Android.Views.WindowFeatures.NoTitle);
SetContentView(Resource.Layout.songSuggestion_layout);
SetViews();
categories = new Categories();
songs = new Songs();
songSuggsted = new Songs();
playlist = new Playlist();
await SetListSongsOfSuggestion();
var metrics = Resources.DisplayMetrics;
//fix video screen height and width
//intDisplayWidth = (FnConvertPixelsToDp(metrics.WidthPixels) + 200);
//intDisplayHeight = (FnConvertPixelsToDp(metrics.HeightPixels)) / (2);
intDisplayHeight = 500;
intDisplayWidth = 1000;
PlayInWebView();
}
public void PlayInWebView()
{
string strUrl = songSuggsted[position].UrlSong;
// string strUrl= "https://www.youtube.com/watch?v=u_VsvZmIWxY";
string id = FnGetVideoID(strUrl);
if (!string.IsNullOrEmpty(id))
{
strUrl = string.Format("http://youtube.com/embed/{0}", id);
}
else
{
Toast.MakeText(this, "Video url is not in correct format", ToastLength.Long).Show();
return;
}
string html = #"<html><body><iframe width=""videoWidth"" height=""videoHeight"" src=""strUrl""></iframe></body></html>";
var myWebView = (WebView)FindViewById(Resource.Id.videoView);
var settings = myWebView.Settings;
settings.JavaScriptEnabled = true;
settings.UseWideViewPort = true;
settings.LoadWithOverviewMode = true;
settings.JavaScriptCanOpenWindowsAutomatically = true;
settings.DomStorageEnabled = true;
settings.SetRenderPriority(WebSettings.RenderPriority.High);
settings.BuiltInZoomControls = false;
settings.JavaScriptCanOpenWindowsAutomatically = true;
myWebView.SetWebChromeClient(new WebChromeClient());
settings.AllowFileAccess = true;
settings.SetPluginState(WebSettings.PluginState.On);
string strYouTubeURL = html.Replace("videoWidth", intDisplayWidth.ToString()).Replace("videoHeight", intDisplayHeight.ToString()).Replace("strUrl", strUrl);
myWebView.LoadDataWithBaseURL(null, strYouTubeURL, "text/html", "UTF-8", null);
}
static string FnGetVideoID(string strVideoURL)
{
const string regExpPattern = #"youtu(?:\.be|be\.com)/(?:.*v(?:/|=)|(?:.*/)?)([a-zA-Z0-9-_]+)";
//for Vimeo: vimeo\.com/(?:.*#|.*/videos/)?([0-9]+)
var regEx = new Regex(regExpPattern);
var match = regEx.Match(strVideoURL);
return match.Success ? match.Groups[1].Value : null;
}
int FnConvertPixelsToDp(float pixelValue)
{
var dp = (int)((pixelValue) / Resources.DisplayMetrics.Density);
return dp;
}
You could try the code below:
Create a webview in android layout.
Xaml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.webkit.WebView
android:id="#+id/webView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Code Behind:
var myWebView = FindViewById<WebView>(Resource.Id.webView1);
WebSettings setting = myWebView.Settings;
setting.JavaScriptEnabled = true;
myWebView.SetWebChromeClient(new WebChromeClient());
myWebView.LoadUrl("https://www.youtube.com/watch?v=6hzrDeceEKc");
Related
I would like to use gstreamer to display udpsrc video, but it does not work.
On the command line it works fine.
"Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg)" will always be False.
Please help me...
send command:
gst-launch-1.0.exe autovideosrc ! videoconvert ! vp8enc deadline=1 ! rtpvp8pay pt=96 ! udpsink port=5200 host=<MY-LOCALIP> async=false
recv command:
gst-launch-1.0.exe udpsrc port=5200 caps="application/x-rtp,payload=(int)96" ! rtpjitterbuffer latency=10 ! rtpvp8depay ! avdec_vp8 output-corrupt=false ! videoconvert ! autovideosink
csharp program:
private void CreatePipeLine()
{
if(pipeline != null)
{
pipeline.SetState(State.Null);
islive = false;
return;
}
pipeline = new Pipeline("pipeline");//"playback");
var udpsrc = Gst.ElementFactory.Make("udpsrc", "source");
udpsrc["port"] = 5200;
//udpsrc["caps"] = "application/x-rtp,payload=96";
var jitter = Gst.ElementFactory.Make("rtpjitterbuffer", "jitter");
jitter["latency"] = 10;
var depay = Gst.ElementFactory.Make("rtpvp8depay", "depay");
var avdec = Gst.ElementFactory.Make("avdec_vp8", "avdec");
avdec["output-corrupt"] = false;
var convert = Gst.ElementFactory.Make("videoconvert", "convert");
var capsRTP = Gst.Global.CapsFromString("application/x-rtp,payload=96");
var mAppSink = new AppSink("appsink");
mAppSink["emit-signals"] = true;
mAppSink["caps"] = capsRTP;
mAppSink.NewSample += OnNewSample;
ink = Gst.ElementFactory.Make("autovideosink", "ink");
pipeline.Add(udpsrc, jitter, depay, avdec, convert, mAppSink); //ink);
udpsrc.Link(jitter);
jitter.Link(depay);
depay.Link(avdec);
avdec.Link(convert);
convert.Link(ink);
Bus bus = pipeline.Bus;
bus.AddSignalWatch();
bus.Message += OnBusMessage;
bus.EnableSyncMessageEmission();
bus.SyncMessage += new SyncMessageHandler(OnBusSynMessage);
/*
VideoSink = new AppSink(ink.Handle);
VideoSink.Drop = true;
VideoSink.MaxLateness = (1000 / 30) * 1000000;
VideoSink.MaxBuffers = 1;
VideoSink.Qos = true;
VideoSink.EnableLastSample = false;
VideoSink.Caps = Gst.Caps.FromString("video/x-raw,format=RGBA");
pipeline.Bus.EnableSyncMessageEmission();
pipeline.Bus.AddSignalWatch();
pipeline.Bus.SyncMessage += OnBusSynMessage;
pipeline.Bus.Message += OnBusMessage;
*/
pipeline.SetState(State.Null);
var ret = pipeline.SetState(State.Ready);
}
private void OnBusSynMessage(object o, SyncMessageArgs sargs)
{
Gst.Message msg = sargs.Message;
if (!Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg)) { return;}
Element src = msg.Src as Element;
if(src == null) { return;}
try { src["force-aspect-ration"] = true;}
catch(PropertyNotFoundException) { }
Element overlay = ((Gst.Bin)src).GetByInterface(VideoOverlayAdapter.GType);
if(overlay == null)
{
System.Diagnostics.Debug.WriteLine($"Overlay is null");
return;
}
_adapter = new VideoOverlayAdapter(overlay.Handle);
_adapter.WindowHandle = _windowHandle;
_adapter.HandleEvents(true);
_isRender = true;
}
Tried this method during playback, but "sample" was null.
var sink = VideoSink;
if(sink == null) { return; }
Sample sample = sink.TryPullSample(5000);
if(sample == null)
{
return;
}
Reference Site:
https://github.com/vladkol/gstreamer-netcore/tree/master/samples/AvaloniaPlayer
how to use application/x-rtp binding with gstreamer-sharp?
I've changed the caps location to udpsrc,
I have tried autovideosink, etc.
Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg)
will be not null only if you have autovideosink in your pipeline. This is because a Window creation request will be created if you have Window "VideoSink" like autovideosink, glvideosink... which implements GstVideoOverlay. (https://gstreamer.freedesktop.org/documentation/opengl/glimagesink.html?gi-language=c#hierarchy see implemented interfaces)
pipeline.Add(udpsrc, jitter, depay, avdec, convert, ink);
Why not setting your pipeline to playing instead of ready ?
var ret = pipeline.SetState(State.Playing);
I am using the following code to upload video on Vimeo. I want to add filename as video title currently I am getting Untitled video with the above code
please guide me how to add Title/Name
public async Task<IActionResult> UploadVideos([FromForm] IFormFile videoFile)
{
string tagName = "tagName";
//var files = Request.Form.Files;
//IFormFile file = files[0];
string uploadStatus = "";
var getVideo = new Video();
try
{
if (videoFile != null)
{
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
VimeoClient vimeoClient = new VimeoClient(accessToken);
var authcheck = await vimeoClient.GetAccountInformationAsync();
if (authcheck.Name != null)
{
IUploadRequest uploadRequest = new UploadRequest();
//Stream stream = file.OpenReadStream();
//using(var memoryStream = new MemoryStream())
//{
// stream.CopyTo(memoryStream);
// memoryStream.ToArray();
//}
BinaryContent binaryContent = new BinaryContent(obj.videoFile.OpenReadStream(), obj.videoFile.ContentType);
int chunkSize = 0;
int contentLength = Convert.ToInt32(obj.videoFile.Length);
int temp1 = contentLength / 1024;
binaryContent.OriginalFileName = "Test Name";
if (temp1 > 1)
{
chunkSize = temp1 / 1024;
if (chunkSize == 0)
{
chunkSize = 1048576;
}
else
{
if (chunkSize > 10)
{
chunkSize = chunkSize / 10;
}
chunkSize = chunkSize * 1048576;
}
}
else
{
chunkSize = 1048576;
}
var checkChunk = chunkSize;
var status = "uploading";
uploadRequest = await vimeoClient.UploadEntireFileAsync(binaryContent, chunkSize, null);
var _tag = tagName;
var tagVideo = await vimeoClient.AddVideoTagAsync(uploadRequest.ClipId.GetValueOrDefault(), _tag);
while (status != "available")
{
getVideo = await vimeoClient.GetVideoAsync(long.Parse(uploadRequest.ClipId.Value.ToString()));
status = getVideo.Status;
}
uploadStatus = String.Concat("file Uploaded ", getVideo.Files[0].LinkSecure);
}
}
return Ok(new { status = uploadStatus, video = getVideo });
}
catch (Exception ex)
{
return BadRequest(ex.ToString());
}
}
I tried to set title with this binaryContent.OriginalFileName but its results untitled video. Please guide by providing the modification required in the api
I try to refer to the Vimeo documentation and come to know that you could use the Pull approach or you could set metadata for the video to set the title.
Video uploads on Vimeo include metadata such as the name of the video and the video's privacy settings. Besides being useful as titles and text descriptors, metadata are also a key component in strategies for search engine optimization.
You can specify values for a video's metadata fields in the body of the initial POST request of an upload, like this:
{
"upload": {
"approach": "tus",
"size": 800000000
},
"name": "My Video",
"privacy": { "view": "nobody" }
}
If you don’t specify a name for your video, we automatically give it the name Untitled, unless you upload it with the pull approach. In that case, we use the file name of the video.
For more detailed information, please refer to Setting video metadata point in this document.
I'm trying to find a working sample to record videos with IOS (using xamarin) but there's always something missing or not working for me.
My best try using several forum posts and samples is the following :
using System;
using CoreGraphics;
using Foundation;
using UIKit;
using AVFoundation;
using CoreVideo;
using CoreMedia;
using CoreFoundation;
using System.IO;
using AssetsLibrary;
namespace avcaptureframes {
public partial class AppDelegate : UIApplicationDelegate {
public static UIImageView ImageView;
UIViewController vc;
AVCaptureSession session;
OutputRecorder outputRecorder;
DispatchQueue queue;
public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
ImageView = new UIImageView (new CGRect (10f, 10f, 200f, 200f));
ImageView.ContentMode = UIViewContentMode.Top;
vc = new UIViewController {
View = ImageView
};
window.RootViewController = vc;
window.MakeKeyAndVisible ();
window.BackgroundColor = UIColor.Black;
if (!SetupCaptureSession ())
window.AddSubview (new UILabel (new CGRect (20f, 20f, 200f, 60f)) {
Text = "No input device"
});
return true;
}
bool SetupCaptureSession ()
{
// configure the capture session for low resolution, change this if your code
// can cope with more data or volume
session = new AVCaptureSession {
SessionPreset = AVCaptureSession.PresetMedium
};
// create a device input and attach it to the session
var captureDevice = AVCaptureDevice.DefaultDeviceWithMediaType (AVMediaType.Video);
if (captureDevice == null) {
Console.WriteLine ("No captureDevice - this won't work on the simulator, try a physical device");
return false;
}
//Configure for 15 FPS. Note use of LockForConigfuration()/UnlockForConfiguration()
NSError error = null;
captureDevice.LockForConfiguration (out error);
if (error != null) {
Console.WriteLine (error);
captureDevice.UnlockForConfiguration ();
return false;
}
if (UIDevice.CurrentDevice.CheckSystemVersion (7, 0))
captureDevice.ActiveVideoMinFrameDuration = new CMTime (1, 15);
captureDevice.UnlockForConfiguration ();
var input = AVCaptureDeviceInput.FromDevice (captureDevice);
if (input == null) {
Console.WriteLine ("No input - this won't work on the simulator, try a physical device");
return false;
}
session.AddInput (input);
// create a VideoDataOutput and add it to the sesion
var settings = new CVPixelBufferAttributes {
PixelFormatType = CVPixelFormatType.CV32BGRA
};
using (var output = new AVCaptureVideoDataOutput { WeakVideoSettings = settings.Dictionary }) {
queue = new DispatchQueue ("myQueue");
outputRecorder = new OutputRecorder ();
output.SetSampleBufferDelegate (outputRecorder, queue);
session.AddOutput (output);
}
session.StartRunning ();
return true;
}
public override void OnActivated (UIApplication application)
{
}
public class OutputRecorder : AVCaptureVideoDataOutputSampleBufferDelegate
{
AVAssetWriter writer=null;
AVAssetWriterInput writerinput= null;
CMTime lastSampleTime;
int frame=0;
NSUrl url;
public OutputRecorder()
{
string tempFile = Path.Combine(Path.GetTempPath(), "NewVideo.mp4");
if (File.Exists(tempFile)) File.Delete(tempFile);
url = NSUrl.FromFilename(tempFile);
NSError assetWriterError;
writer = new AVAssetWriter(url, AVFileType.Mpeg4, out assetWriterError);
var outputSettings = new AVVideoSettingsCompressed()
{
Height = 300,
Width = 300,
Codec = AVVideoCodec.H264,
CodecSettings = new AVVideoCodecSettings
{
AverageBitRate = 1000000
}
};
writerinput = new AVAssetWriterInput(mediaType: AVMediaType.Video, outputSettings: outputSettings);
writerinput.ExpectsMediaDataInRealTime = false;
writer.AddInput(writerinput);
}
public override void DidOutputSampleBuffer (AVCaptureOutput captureOutput, CMSampleBuffer sampleBuffer, AVCaptureConnection connection)
{
try
{
lastSampleTime = sampleBuffer.PresentationTimeStamp;
var image = ImageFromSampleBuffer(sampleBuffer);
if (frame == 0)
{
writer.StartWriting();
writer.StartSessionAtSourceTime(lastSampleTime);
frame = 1;
}
String infoString = "";
if (writerinput.ReadyForMoreMediaData)
{
if (!writerinput.AppendSampleBuffer(sampleBuffer))
{
infoString = "Failed to append sample buffer";
}
else
{
infoString = String.Format("{0} frames captured", frame++);
}
}
else
{
infoString = "Writer not ready";
}
Console.WriteLine(infoString);
ImageView.BeginInvokeOnMainThread(() => ImageView.Image = image);
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
sampleBuffer.Dispose();
}
}
UIImage ImageFromSampleBuffer (CMSampleBuffer sampleBuffer)
{
// Get the CoreVideo image
using (var pixelBuffer = sampleBuffer.GetImageBuffer () as CVPixelBuffer)
{
// Lock the base address
pixelBuffer.Lock (CVOptionFlags.None);
// Get the number of bytes per row for the pixel buffer
var baseAddress = pixelBuffer.BaseAddress;
var bytesPerRow = (int)pixelBuffer.BytesPerRow;
var width = (int)pixelBuffer.Width;
var height = (int)pixelBuffer.Height;
var flags = CGBitmapFlags.PremultipliedFirst | CGBitmapFlags.ByteOrder32Little;
// Create a CGImage on the RGB colorspace from the configured parameter above
using (var cs = CGColorSpace.CreateDeviceRGB ())
{
using (var context = new CGBitmapContext (baseAddress, width, height, 8, bytesPerRow, cs, (CGImageAlphaInfo)flags))
{
using (CGImage cgImage = context.ToImage ())
{
pixelBuffer.Unlock (CVOptionFlags.None);
return UIImage.FromImage (cgImage);
}
}
}
}
}
void TryDispose (IDisposable obj)
{
if (obj != null)
obj.Dispose ();
}
}
}
}
This works displaying live camera image and I get "frames captured" message in consol but I don't find how to record to file.
I read somewhere about adding VideoCapture but I don't know how to link with my code.
Any help will is welcome.
From your code, in the construct of class OutputRecorder you have defined the url where you want to save the recording:
string tempFile = Path.Combine(Path.GetTempPath(), "NewVideo.mp4");
if (File.Exists(tempFile)) File.Delete(tempFile);
url = NSUrl.FromFilename(tempFile);
It means you want to save the video in the tmp folder in the app's sandbox. If you want to use the video sometime later, I recommend you to change the folder to documents by using:
string filePath = Path.Combine(NSSearchPath.GetDirectories(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User)[0], "NewVideo.mp4");
I notice that you have called session.StartRunning(); in the method bool SetupCaptureSession() to start recording. please add session.StopRunning(); to end recording then the video will be saved in the path we just defined above.
Moreover, you can retrieve the video with the path like:
NSData videoData = NSData.FromFile(filePath);
I'm developing a ASP.NET MVC website which has a page that downloads a power point file created by Interop.PowePoint.dll. When I deploy a release of the website to my own machine in IIS, the download stops working and give the error from the description.
Here is my code:
MessageFilter.Register();
// This registers the IOleMessageFilter to handle any threading
// errors.
Thread.Sleep(3000);
//creating powerpoint aaplication
Application powerPointApplication = new Application();
//powerPointApplication.Visible = MsoTriState.msoFalse;
var pptPresentation = powerPointApplication.Presentations.Add(MsoTriState.msoFalse);
Microsoft.Office.Interop.PowerPoint.CustomLayout customLayout =
pptPresentation.SlideMaster.CustomLayouts[Microsoft.Office.Interop.PowerPoint.PpSlideLayout.ppLayoutText];
//Step5.Insert a slide by calling the Add method on the Presentation.Slides collection, and add some texts to the slide.
var index = 1;
var oSlides = pptPresentation.Slides;
if (model.Configuration.Ratio == "4:3")
{
pptPresentation.PageSetup.SlideSize = PpSlideSizeType.ppSlideSizeOnScreen;
}
foreach (var slide in model.Slides)
{
var oSlide = oSlides.AddSlide(index, customLayout);
oSlide.FollowMasterBackground = MsoTriState.msoFalse;
//oSlide.Background.Fill.BackColor.RGB = Convert.ToInt32(ExtractHex(model.Configuration.Background), 16);
oSlide.Background.Fill.BackColor.RGB = ColorTranslator.ToOle(HexToColor(model.Configuration.Background));
//content
var oShape = oSlide.Shapes[2];
//oShape.LockAspectRatio = MsoTriState.msoTriStateToggle;
var oTxtFrame = oShape.TextFrame;
var oTxtRange = oTxtFrame.TextRange;
oTxtRange.Text = FormatText(slide);
//oTxtRange.Font.Size = model.Configuration.FontSize;
oTxtRange.Font.Color.RGB = ColorTranslator.ToOle(HexToColor(model.Configuration.Forecolor));
oTxtRange.Font.Size = GetFontSize(slide);
if (model.Configuration.Font != null)
{
oTxtRange.Font.Name = model.Configuration.Font;
}
//oTxtRange.Font.Bold = MsoTriState.msoTrue;
oShape.TextEffect.Alignment = MsoTextEffectAlignment.msoTextEffectAlignmentCentered;
oTxtFrame.HorizontalAnchor = MsoHorizontalAnchor.msoAnchorCenter;
//oTxtFrame.VerticalAnchor = MsoVerticalAnchor.msoAnchorMiddle;
var format = oTxtRange.Paragraphs().ParagraphFormat;
format.Bullet.Type = PpBulletType.ppBulletNone;
//format.Alignment = PpParagraphAlignment.ppAlignCenter;
index++;
}
//Step6.Save the presentation as a pptx file and close it.
model.Name = "Praiser.ppt";
string fileFullPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\" + model.Name;
pptPresentation.SaveAs(fileFullPath, PpSaveAsFileType.ppSaveAsOpenXMLPresentation, MsoTriState.msoTriStateMixed);
pptPresentation.Close();
powerPointApplication.Quit();
MessageFilter.Revoke();
return File(fileFullPath, "application/vnd.ms-powerpoint", model.Name);
I have created a package that requires the creation of an extra MediaType, since packaging it is not available in the package screens.
To circumvent this issue I've started researching into creating a new MediaType via Package Actions. Lastly started following this quick tutorial Umbraco V7 Compatible Packages
Have added a class (below), compiled it (in Debug Mode), copied it to the /bin/ folder of Umbraco, then added the dll as a package file, along with everything else.
Then, on another instance of Umbraco, installed it from local package.
Problem is: IT IS NOT WORKING!
At the moment I have no idea of what could be wrong, so if anyone has any suggestions, they're welcome.
Below is the class I have created:
using System;
using System.Collections.Generic;
using System.Xml;
using umbraco.interfaces;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace Social_Media_Channels.Installer
{
public class AddMediaAction : IPackageAction
{
public string Alias()
{
return "SocialMediaChannels_AddThemes";
}
public bool Execute(string packageName, XmlNode xmlData)
{
string STEP = string.Empty;
if (UmbracoVersion.Current.Major >= 7)
{
try
{
#region MediaType
STEP = "Adding MediaType";
LogHelper.Info(typeof(AddMediaAction), STEP);
MediaHelper.AddMediaType();
#endregion
#region Theme Images
STEP = "Adding Media Themes";
LogHelper.Info(typeof(AddMediaAction), STEP);
#endregion
return true;
}
catch (Exception ex)
{
var message = string.Concat("Error at install ", Alias(), " package action: " + STEP, ex);
LogHelper.Error(typeof(AddMediaAction), message, ex);
return false;
}
}
return false;
}
public bool Undo(string packageName, XmlNode xmlData)
{
if (UmbracoVersion.Current.Major >= 7)
{
//MediaType mediaType = new MediaType();
}
return true;
}
public XmlNode SampleXml()
{
var xml = string.Format("<Action runat=\"install\" undo=\"true\" alias=\"{0}\" />", Alias());
XmlDocument x = new XmlDocument();
x.LoadXml(xml);
return x;
}
}
}
Below is the Helper Class:
using System.Collections.Generic;
using Umbraco.Core.Models;
namespace Social_Media_Channels.Installer
{
public class MediaHelper
{
private readonly static string MediaTypeName = "Social Media Theme";
// LogHelper.Error<TranslationHelper>("Failed to add Opening Soon localization values to language file", ex);
public static void AddMediaType()
{
MediaType mediaType = new MediaType(0);
mediaType.AllowedAsRoot = true;
mediaType.Name = MediaTypeName;
mediaType.Description = "Container for the Social Media Channel Theme Images";
mediaType.IsContainer = true;
//Allowed child nodes
var children = new List<ContentTypeSort>
{
new ContentTypeSort(1031, 0),
new ContentTypeSort(1032, 1)
};
mediaType.AllowedContentTypes = children;
//Add properties
var name = new PropertyType(new DataTypeDefinition(-88, "themeName"));
name.Name = "Theme Name";
name.Description = "Name for the theme";
var url = new PropertyType(new DataTypeDefinition(-88, "themeUrl"));
url.Name = "Theme Url";
url.Description = "Url for the original theme";
var createdBy = new PropertyType(new DataTypeDefinition(-88, "createdBy"));
createdBy.Name = "Created By";
createdBy.Description = "Theme Author";
var createdDate = new PropertyType(new DataTypeDefinition(-41, "createdDate"));
createdDate.Name = "Created Date";
createdDate.Description = "Date the Theme was created";
mediaType.AddPropertyType(name, "Image");
mediaType.AddPropertyType(url, "Image");
mediaType.AddPropertyType(createdBy, "Image");
mediaType.AddPropertyType(createdDate, "Image");
}
public static void RemoveMediaType()
{
}
}
}
And in Package Actions (Umbraco) I have added the following line
<Action runat="install" undo="true" alias="SocialMediaChannels_AddThemes" />
Suggestions or corrections? Anyone?
Turns out there were a lot of things wrong with my original code. Finally got it working after lots of investigation.
Basically the Adding (which was causing it to fail) became:
public static void AddMediaType()
{
MediaType mediaType = new MediaType(-1);
mediaType.AllowedAsRoot = true;
mediaType.Name = NAME;
mediaType.Description = "Container for the Social Media Channel Theme Images";
mediaType.IsContainer = true;
mediaType.Icon = "icon-picture";
mediaType.Alias = ALIAS;
//Allowed child nodes
var children = new List<ContentTypeSort>
{
new ContentTypeSort(FOLDER_ID, 0),
new ContentTypeSort(IMAGE_ID, 1)
};
mediaType.AllowedContentTypes = children;
DataTypeService dataTypeService = (DataTypeService)ApplicationContext.Current.Services.DataTypeService;
//Add properties
var name = new PropertyType(dataTypeService.GetDataTypeDefinitionById(TEXT_ID), "themeName");
name.Name = "Theme Name";
name.Description = "Name for the theme";
name.SortOrder = 0;
var url = new PropertyType(dataTypeService.GetDataTypeDefinitionById(TEXT_ID), "themeUrl");
url.Name = "Theme Url";
url.Description = "Url for the original theme";
url.SortOrder = 1;
var createdBy = new PropertyType(dataTypeService.GetDataTypeDefinitionById(TEXT_ID), "createdBy");
createdBy.Name = "Created By";
createdBy.Description = "Theme Author";
createdBy.SortOrder = 2;
var createdDate = new PropertyType(dataTypeService.GetDataTypeDefinitionById(DATE_ID), "createdDate");
createdDate.Name = "Created Date";
createdDate.Description = "Date the Theme was created";
createdDate.SortOrder = 3;
mediaType.AddPropertyType(name, "Image");
mediaType.AddPropertyType(url, "Image");
mediaType.AddPropertyType(createdBy, "Image");
mediaType.AddPropertyType(createdDate, "Image");
ContentTypeService contentTypeService = (ContentTypeService)ApplicationContext.Current.Services.ContentTypeService;
contentTypeService.Save(mediaType);
}
And now it works!
By comparing with the DAMP source code (DAMP) I noticed that the new MediaType class Umbraco.Core.Models.MediaType is missing the Save() method, so no matter how I tested, it simply would not save the new media type.
Anyway, also by using DAMP's example (good old copy/paste), that uses the old assemblies and shows a message 'OBSOLETE', came up with a new version of the code, which worked as expected.
What the code with the old libraries looks like:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Xml;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.datatype;
using umbraco.cms.businesslogic.datatype.controls;
using umbraco.cms.businesslogic.media;
using umbraco.cms.businesslogic.packager.standardPackageActions;
using umbraco.DataLayer;
using umbraco.interfaces;
using umbraco.IO;
namespace SocialMediaChannels
{
public class AddSocialMediaThemes : IPackageAction
{
private readonly static string MediaTypeName = "Social Media Theme";
private readonly static int LABEL_ID = -92;
private readonly static int UPLOAD_ID = -90;
private readonly static int TEXT_ID = -88;
private readonly static int DATE_ID = -41;
private readonly static int IMAGE_ID = 1031;
private readonly static int FOLDER_ID = 1032;
public IDataType uploadField = new Factory().GetNewObject(new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c"));
protected static ISqlHelper SqlHelper
{
get
{
return umbraco.BusinessLogic.Application.SqlHelper;
}
}
public string Alias()
{
return "SocialMediaChannels_AddSocialMediaThemes";
}
public bool Execute(string packageName, XmlNode xmlData)
{
bool flag;
try
{
#region MediaType
User adminUser = new User(0);
MediaType theme = CreateMediaType(adminUser, MediaTypeName);
MediaType folder = MediaType.GetByAlias("Folder");
int[] folderStructure = folder.AllowedChildContentTypeIDs;
int newsize = folderStructure.Length + 1;
Array.Resize(ref folderStructure, newsize);
folderStructure[newsize - 1] = theme.Id;
folder.AllowedChildContentTypeIDs = folderStructure;
MediaType image = MediaType.GetByAlias(MediaTypeName);
#endregion
#region Theme Images
#endregion
flag = true;
}
catch
{
flag = false;
}
return flag;
}
public bool Undo(string packageName, XmlNode xmlData)
{
bool flag;
try
{
//remove themes
flag = true;
}
catch
{
flag = false;
}
return flag;
}
public XmlNode SampleXml()
{
string sample = string.Format("<Action runat=\"install\" undo=\"true/false\" alias=\"{0}\" ></Action>", Alias());
return helper.parseStringToXmlNode(sample);
}
/// <summary>
/// Create a Media Type.
/// </summary>
/// <param name="adminUser"></param>
/// <param name="mediaTypeName"></param>
/// <returns></returns>
private MediaType CreateMediaType(User adminUser, string mediaTypeName)
{
MediaType mediaType = MediaType.MakeNew(adminUser, mediaTypeName);
int[] typeIds = { FOLDER_ID, IMAGE_ID };
mediaType.AllowAtRoot = true;
mediaType.Text = MediaTypeName;
mediaType.Description = "Container for the Social Media Channel Theme Images";
mediaType.IsContainerContentType = true;
mediaType.AllowedChildContentTypeIDs = typeIds;
//Add properties
mediaType.AddPropertyType(new DataTypeDefinition(UPLOAD_ID), "umbracoFile", "Upload image");
mediaType.AddPropertyType(new DataTypeDefinition(LABEL_ID), "umbracoWidth", "Width");
mediaType.AddPropertyType(new DataTypeDefinition(LABEL_ID), "umbracoHeight", "Height");
mediaType.AddPropertyType(new DataTypeDefinition(LABEL_ID), "umbracoBytes", "Size");
mediaType.AddPropertyType(new DataTypeDefinition(LABEL_ID), "umbracoExtension", "Type");
mediaType.AddPropertyType(new DataTypeDefinition(TEXT_ID), "themeName", "Name of the Social Channel Theme");
mediaType.AddPropertyType(new DataTypeDefinition(TEXT_ID), "themeUrl", "Url for the Theme");
mediaType.AddPropertyType(new DataTypeDefinition(TEXT_ID), "createdBy", "Author of the Theme");
mediaType.AddPropertyType(new DataTypeDefinition(DATE_ID), "createdDate", "Date the Theme was created");
mediaType.Text = mediaTypeName;
mediaType.IconUrl = "mediaPhoto.gif";
mediaType.Save();
return mediaType;
}
}
}
And the Action looks like this
<Action runat="install" undo="true" alias="SocialMediaChannels_AddSocialMediaThemes" ></Action>