Add MTP plugin using routines adapted from banshee, not sure if this works or not
This commit is contained in:
parent
8d70789cfb
commit
92606e1a0f
@ -0,0 +1,33 @@
|
||||
//
|
||||
// Methods.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2019 Mike Becker
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace UniversalEditor.Accessors.MTP.Internal.Linux
|
||||
{
|
||||
public class Methods
|
||||
{
|
||||
public const string LIBRARY_FILENAME = "gio";
|
||||
|
||||
[DllImport(LIBRARY_FILENAME)]
|
||||
public static extern IntPtr g_file_new_for_uri(string uri);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,149 @@
|
||||
/***************************************************************************
|
||||
* AbstractTrackList.cs
|
||||
*
|
||||
* Copyright (C) 2008 Novell
|
||||
* Copyright (C) 2010 Alan McGovern
|
||||
* Authors:
|
||||
* Gabriel Burt (gburt@novell.com)
|
||||
* Alan McGovern (alan.mcgovern@gmail.com)
|
||||
****************************************************************************/
|
||||
|
||||
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mtp
|
||||
{
|
||||
public abstract class AbstractTrackList
|
||||
{
|
||||
private bool saved;
|
||||
private List<uint> track_ids;
|
||||
private MtpDevice device;
|
||||
|
||||
public abstract uint Count { get; protected set; }
|
||||
public abstract string Name { get; set; }
|
||||
protected abstract IntPtr TracksPtr { get; set; }
|
||||
|
||||
protected abstract int Create();
|
||||
protected abstract int Update();
|
||||
|
||||
public bool Saved { get { return saved; } }
|
||||
protected MtpDevice Device { get { return device; } }
|
||||
|
||||
public IList<uint> TrackIds
|
||||
{
|
||||
get { return track_ids; }
|
||||
}
|
||||
|
||||
protected AbstractTrackList(MtpDevice device)
|
||||
{
|
||||
if (device == null)
|
||||
{
|
||||
throw new ArgumentNullException("device");
|
||||
}
|
||||
|
||||
this.device = device;
|
||||
|
||||
if (track_ids == null)
|
||||
{
|
||||
track_ids = new List<uint>();
|
||||
}
|
||||
}
|
||||
|
||||
internal AbstractTrackList(MtpDevice device, IntPtr tracks, uint count) : this(device)
|
||||
{
|
||||
this.saved = true;
|
||||
this.track_ids = new List<uint>();
|
||||
|
||||
if (tracks != IntPtr.Zero)
|
||||
{
|
||||
for (int i = 0; i < (int)count; i++)
|
||||
track_ids.Add((uint)Marshal.ReadInt32(tracks, sizeof(int) * i));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddTrack(Track track)
|
||||
{
|
||||
AddTrack(track.FileId);
|
||||
}
|
||||
|
||||
public void AddTrack(uint track_id)
|
||||
{
|
||||
track_ids.Add(track_id);
|
||||
Count++;
|
||||
}
|
||||
|
||||
public void RemoveTrack(Track track)
|
||||
{
|
||||
RemoveTrack(track.FileId);
|
||||
}
|
||||
|
||||
public void RemoveTrack(uint track_id)
|
||||
{
|
||||
track_ids.Remove(track_id);
|
||||
Count--;
|
||||
}
|
||||
|
||||
public void ClearTracks()
|
||||
{
|
||||
track_ids.Clear();
|
||||
Count = 0;
|
||||
}
|
||||
|
||||
public virtual void Save()
|
||||
{
|
||||
Count = (uint)track_ids.Count;
|
||||
|
||||
if (TracksPtr != IntPtr.Zero)
|
||||
throw new InvalidOperationException("TracksPtr must be NULL when Save is called");
|
||||
|
||||
try
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
TracksPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint)) * (int)Count);
|
||||
for (int i = 0; i < track_ids.Count; i++)
|
||||
Marshal.WriteInt32(TracksPtr, i * sizeof(int), (int)track_ids[i]);
|
||||
}
|
||||
|
||||
if (saved)
|
||||
{
|
||||
saved = Update() == 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
saved = Create() == 0;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (TracksPtr != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(TracksPtr);
|
||||
TracksPtr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,234 @@
|
||||
/***************************************************************************
|
||||
* Album.cs
|
||||
*
|
||||
* Copyright (C) 2008 Novell
|
||||
* Authors:
|
||||
* Gabriel Burt (gburt@novell.com)
|
||||
****************************************************************************/
|
||||
|
||||
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mtp
|
||||
{
|
||||
public class Album : AbstractTrackList
|
||||
{
|
||||
internal static List<Album> GetAlbums(MtpDevice device)
|
||||
{
|
||||
List<Album> albums = new List<Album>();
|
||||
|
||||
IntPtr ptr = LIBMTP_Get_Album_List(device.Handle);
|
||||
while (ptr != IntPtr.Zero)
|
||||
{
|
||||
// Destroy the struct *after* we use it to ensure we don't access freed memory
|
||||
// for the 'tracks' variable
|
||||
AlbumStruct d = (AlbumStruct)Marshal.PtrToStructure(ptr, typeof(AlbumStruct));
|
||||
albums.Add(new Album(device, d));
|
||||
LIBMTP_destroy_album_t(ptr);
|
||||
ptr = d.next;
|
||||
}
|
||||
|
||||
return albums;
|
||||
}
|
||||
|
||||
private AlbumStruct album;
|
||||
|
||||
public uint AlbumId
|
||||
{
|
||||
get { return Saved ? album.album_id : 0; }
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return album.name; }
|
||||
set { album.name = value; }
|
||||
}
|
||||
|
||||
public string Artist
|
||||
{
|
||||
get { return album.artist; }
|
||||
set { album.artist = value; }
|
||||
}
|
||||
|
||||
public string Genre
|
||||
{
|
||||
get { return album.genre; }
|
||||
set { album.genre = value; }
|
||||
}
|
||||
|
||||
public string Composer
|
||||
{
|
||||
get
|
||||
{
|
||||
return album.composer;
|
||||
}
|
||||
set
|
||||
{
|
||||
album.composer = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override uint Count
|
||||
{
|
||||
get { return album.no_tracks; }
|
||||
protected set { album.no_tracks = value; }
|
||||
}
|
||||
|
||||
protected override IntPtr TracksPtr
|
||||
{
|
||||
get { return album.tracks; }
|
||||
set { album.tracks = value; }
|
||||
}
|
||||
|
||||
public Album(MtpDevice device, string name, string artist, string genre, string composer) : base(device)
|
||||
{
|
||||
Name = name;
|
||||
Artist = artist;
|
||||
Genre = genre;
|
||||
Composer = composer;
|
||||
Count = 0;
|
||||
}
|
||||
|
||||
internal Album(MtpDevice device, AlbumStruct album) : base(device, album.tracks, album.no_tracks)
|
||||
{
|
||||
// Once we've loaded the tracks, set the TracksPtr to NULL as it
|
||||
// will be freed when the Album constructor is finished.
|
||||
this.album = album;
|
||||
TracksPtr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
public override void Save()
|
||||
{
|
||||
Save(null, 0, 0);
|
||||
}
|
||||
|
||||
public void Save(byte[] cover_art, uint width, uint height)
|
||||
{
|
||||
base.Save();
|
||||
if (Saved)
|
||||
{
|
||||
if (cover_art == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FileSampleData cover = new FileSampleData();
|
||||
cover.data = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(byte)) * cover_art.Length);
|
||||
Marshal.Copy(cover_art, 0, cover.data, cover_art.Length);
|
||||
cover.size = (ulong)cover_art.Length;
|
||||
cover.width = width;
|
||||
cover.height = height;
|
||||
cover.filetype = FileType.JPEG;
|
||||
|
||||
if (FileSample.LIBMTP_Send_Representative_Sample(Device.Handle, AlbumId, ref cover) != 0)
|
||||
{
|
||||
//Console.WriteLine ("Failed to send representative sample file for album {0} (id {1})", Name, AlbumId);
|
||||
}
|
||||
Marshal.FreeHGlobal(cover.data);
|
||||
}
|
||||
}
|
||||
|
||||
protected override int Create()
|
||||
{
|
||||
return LIBMTP_Create_New_Album(Device.Handle, ref album);
|
||||
}
|
||||
|
||||
protected override int Update()
|
||||
{
|
||||
return LIBMTP_Update_Album(Device.Handle, ref album);
|
||||
}
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
MtpDevice.LIBMTP_Delete_Object(Device.Handle, AlbumId);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("Album < Id: {4}, '{0}' by '{1}', genre '{2}', tracks {3} >", Name, Artist, Genre, Count, AlbumId);
|
||||
}
|
||||
|
||||
public static Album GetById(MtpDevice device, uint id)
|
||||
{
|
||||
IntPtr ptr = Album.LIBMTP_Get_Album(device.Handle, id);
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Destroy the struct after we use it to prevent accessing freed memory
|
||||
// in the 'tracks' variable
|
||||
AlbumStruct album = (AlbumStruct)Marshal.PtrToStructure(ptr, typeof(AlbumStruct));
|
||||
var ret = new Album(device, album);
|
||||
LIBMTP_destroy_album_t(ptr);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
//[DllImport (MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
//internal static extern IntPtr LIBMTP_new_album_t (); // LIBMTP_album_t*
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
static extern void LIBMTP_destroy_album_t(IntPtr album);
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
static extern IntPtr LIBMTP_Get_Album_List(MtpDeviceHandle handle); // LIBMTP_album_t*
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
static extern IntPtr LIBMTP_Get_Album(MtpDeviceHandle handle, uint albumId); // LIBMTP_album_t*
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern int LIBMTP_Create_New_Album(MtpDeviceHandle handle, ref AlbumStruct album);
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
static extern int LIBMTP_Update_Album(MtpDeviceHandle handle, ref AlbumStruct album);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AlbumStruct
|
||||
{
|
||||
public uint album_id;
|
||||
public uint parent_id;
|
||||
public uint storage_id;
|
||||
|
||||
[MarshalAs(UnmanagedType.LPStr)]
|
||||
public string name;
|
||||
|
||||
[MarshalAs(UnmanagedType.LPStr)]
|
||||
public string artist;
|
||||
|
||||
[MarshalAs(UnmanagedType.LPStr)]
|
||||
public string composer;
|
||||
|
||||
[MarshalAs(UnmanagedType.LPStr)]
|
||||
public string genre;
|
||||
|
||||
public IntPtr tracks;
|
||||
public uint no_tracks;
|
||||
|
||||
public IntPtr next;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
/***************************************************************************
|
||||
* Error.cs
|
||||
*
|
||||
* Copyright (C) 2006-2007 Alan McGovern
|
||||
* Authors:
|
||||
* Alan McGovern (alan.mcgovern@gmail.com)
|
||||
****************************************************************************/
|
||||
|
||||
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mtp
|
||||
{
|
||||
public class LibMtpException : Exception
|
||||
{
|
||||
public LibMtpException(ErrorCode error) : this(error, error.ToString(), null)
|
||||
{
|
||||
}
|
||||
|
||||
public LibMtpException(ErrorCode error, string message) : this(error, message, null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public LibMtpException(ErrorCode error, string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
internal static void CheckErrorStack(MtpDeviceHandle handle)
|
||||
{
|
||||
IntPtr ptr = MtpDevice.GetErrorStack(handle);
|
||||
if (ptr == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
LibMtpException ex = null;
|
||||
while (ptr != IntPtr.Zero)
|
||||
{
|
||||
Error e = (Error)Marshal.PtrToStructure(ptr, typeof(Error));
|
||||
ex = new LibMtpException(e.errornumber, e.error_text, ex);
|
||||
ptr = e.next;
|
||||
}
|
||||
|
||||
// Once we throw the exception, clear the error stack
|
||||
MtpDevice.ClearErrorStack(handle);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public struct Error
|
||||
{
|
||||
public ErrorCode errornumber;
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string error_text;
|
||||
public IntPtr next; // LIBMTP_error_t*
|
||||
|
||||
public static void CheckError(ErrorCode errorCode)
|
||||
{
|
||||
if (errorCode != ErrorCode.None)
|
||||
{
|
||||
throw new LibMtpException(errorCode, errorCode.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
/***************************************************************************
|
||||
* MtpDevice.cs
|
||||
*
|
||||
* Copyright (C) 2006-2007 Alan McGovern
|
||||
* Authors:
|
||||
* Alan McGovern (alan.mcgovern@gmail.com)
|
||||
****************************************************************************/
|
||||
|
||||
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mtp
|
||||
{
|
||||
public enum ErrorCode
|
||||
{
|
||||
/*LIBMTP_ERROR_NONE,
|
||||
LIBMTP_ERROR_GENERAL,
|
||||
LIBMTP_ERROR_PTP_LAYER,
|
||||
LIBMTP_ERROR_USB_LAYER,
|
||||
LIBMTP_ERROR_MEMORY_ALLOCATION,
|
||||
LIBMTP_ERROR_NO_DEVICE_ATTACHED,
|
||||
LIBMTP_ERROR_STORAGE_FULL,
|
||||
LIBMTP_ERROR_CONNECTING,
|
||||
LIBMTP_ERROR_CANCELLED*/
|
||||
None,
|
||||
General,
|
||||
PtpLayer,
|
||||
UsbLayer,
|
||||
MemoryAllocation,
|
||||
NoDeviceAttached,
|
||||
StorageFull,
|
||||
Connecting,
|
||||
Cancelled
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
/***************************************************************************
|
||||
* File.cs
|
||||
*
|
||||
* Copyright (C) 2006-2007 Alan McGovern
|
||||
* Authors:
|
||||
* Alan McGovern (alan.mcgovern@gmail.com)
|
||||
****************************************************************************/
|
||||
|
||||
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mtp
|
||||
{
|
||||
public class File
|
||||
{
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_new_file_t(); // LIBMTP_file_t *
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void LIBMTP_destroy_file_t(ref File file); // LIBMTP_file_t *
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern string LIBMTP_Get_Filetype_Description(FileType type); // char const *
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_Get_Filelisting(MtpDeviceHandle handle); // LIBMTP_file_t *
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_Get_Filelisting_With_Callback(MtpDeviceHandle handle, ProgressFunction function, IntPtr data); // LIBMTP_file_t *
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_Get_Filemetadata(MtpDeviceHandle handle, uint fileid); // LIBMTP_file_t *
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int LIBMTP_Get_File_To_File(MtpDeviceHandle handle, uint fileId, string path, ProgressFunction function, IntPtr data);
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void LIBMTP_destroy_filesampledata_t(ref FileSampleData data); // LIBMTP_filesampledata_t *
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int LIBMTP_Get_Representative_Sample_Format(MtpDeviceHandle handle, FileType type, IntPtr data_array);
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int LIBMTP_Send_Representative_Sample(MtpDeviceHandle handle, uint id, ref FileSampleData sample);
|
||||
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct FileStruct
|
||||
{
|
||||
public int item_id;
|
||||
public int parent_id;
|
||||
public int storage_id;
|
||||
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string filename;
|
||||
public long filesize;
|
||||
public FileType filetype;
|
||||
public IntPtr next; // LIBMTP_file_t*
|
||||
public File NextFile
|
||||
{
|
||||
get
|
||||
{
|
||||
if (next == IntPtr.Zero)
|
||||
return null;
|
||||
return (File)Marshal.PtrToStructure(next, typeof(File));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
/***************************************************************************
|
||||
* FileSampleData.cs
|
||||
*
|
||||
* Copyright (C) 2006-2007 Alan McGovern
|
||||
* Authors:
|
||||
* Alan McGovern (alan.mcgovern@gmail.com)
|
||||
****************************************************************************/
|
||||
|
||||
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mtp
|
||||
{
|
||||
internal static class FileSample
|
||||
{
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void LIBMTP_destroy_filesampledata_t(ref FileSampleData data); // LIBMTP_filesampledata_t *
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int LIBMTP_Get_Representative_Sample_Format(MtpDeviceHandle handle, FileType type, IntPtr data_array);
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int LIBMTP_Send_Representative_Sample(MtpDeviceHandle handle, uint id, ref FileSampleData sample);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct FileSampleData
|
||||
{
|
||||
public uint width;
|
||||
public uint height;
|
||||
public uint duration;
|
||||
public FileType filetype;
|
||||
public ulong size;
|
||||
public IntPtr data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
/***************************************************************************
|
||||
* Enums.cs
|
||||
*
|
||||
* Copyright (C) 2006-2007 Alan McGovern
|
||||
* Authors:
|
||||
* Alan McGovern (alan.mcgovern@gmail.com)
|
||||
****************************************************************************/
|
||||
|
||||
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mtp
|
||||
{
|
||||
public enum FileType
|
||||
{
|
||||
FOLDER,
|
||||
WAV,
|
||||
MP3,
|
||||
WMA,
|
||||
OGG,
|
||||
AUDIBLE,
|
||||
MP4,
|
||||
UNDEF_AUDIO,
|
||||
WMV,
|
||||
AVI,
|
||||
MPEG,
|
||||
ASF,
|
||||
QT,
|
||||
UNDEF_VIDEO,
|
||||
JPEG,
|
||||
JFIF,
|
||||
TIFF,
|
||||
BMP,
|
||||
GIF,
|
||||
PICT,
|
||||
PNG,
|
||||
VCALENDAR1,
|
||||
VCALENDAR2,
|
||||
VCARD2,
|
||||
VCARD3,
|
||||
WINDOWSIMAGEFORMAT,
|
||||
WINEXEC,
|
||||
TEXT,
|
||||
HTML,
|
||||
FIRMWARE,
|
||||
AAC,
|
||||
MEDIACARD,
|
||||
FLAC,
|
||||
MP2,
|
||||
M4A,
|
||||
DOC,
|
||||
XML,
|
||||
XLS,
|
||||
PPT,
|
||||
MHT,
|
||||
JP2,
|
||||
JPX,
|
||||
ALBUM,
|
||||
PLAYLIST,
|
||||
UNKNOWN
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,313 @@
|
||||
/***************************************************************************
|
||||
* Folder.cs
|
||||
*
|
||||
* Copyright (C) 2006-2007 Alan McGovern
|
||||
* Authors:
|
||||
* Alan McGovern (alan.mcgovern@gmail.com)
|
||||
****************************************************************************/
|
||||
|
||||
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mtp
|
||||
{
|
||||
public class Folder
|
||||
{
|
||||
private MtpDevice device;
|
||||
private uint folderId;
|
||||
private uint parentId;
|
||||
private string name;
|
||||
|
||||
internal uint FolderId
|
||||
{
|
||||
get { return folderId; }
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
}
|
||||
|
||||
internal uint ParentId
|
||||
{
|
||||
get { return parentId; }
|
||||
}
|
||||
|
||||
internal Folder(uint folderId, uint parentId, string name, MtpDevice device)
|
||||
{
|
||||
this.device = device;
|
||||
this.folderId = folderId;
|
||||
this.parentId = parentId;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
internal Folder(FolderStruct folder, MtpDevice device)
|
||||
: this(folder.folder_id, folder.parent_id, folder.name, device)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Folder AddChild(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
throw new ArgumentNullException("name");
|
||||
|
||||
// First create the folder on the device and check for error
|
||||
uint id = CreateFolder(device.Handle, name, FolderId);
|
||||
|
||||
FolderStruct f = new FolderStruct();
|
||||
f.folder_id = id;
|
||||
f.parent_id = FolderId;
|
||||
f.name = name;
|
||||
|
||||
return new Folder(f, device);
|
||||
}
|
||||
|
||||
public List<Folder> GetChildren()
|
||||
{
|
||||
IntPtr root = GetFolderList(device.Handle);
|
||||
IntPtr ptr = Find(root, folderId);
|
||||
|
||||
FolderStruct f = (FolderStruct)Marshal.PtrToStructure(ptr, typeof(FolderStruct));
|
||||
|
||||
ptr = f.child;
|
||||
List<Folder> folders = new List<Folder>();
|
||||
while (ptr != IntPtr.Zero)
|
||||
{
|
||||
FolderStruct folder = (FolderStruct)Marshal.PtrToStructure(ptr, typeof(FolderStruct));
|
||||
folders.Add(new Folder(folder, device));
|
||||
ptr = folder.sibling;
|
||||
}
|
||||
|
||||
LIBMTP_destroy_folder_t(root);
|
||||
return folders;
|
||||
}
|
||||
|
||||
private Folder CreateParentFolder()
|
||||
{
|
||||
return Find(device, parentId);
|
||||
}
|
||||
|
||||
public bool HasAncestor(Folder ancestor)
|
||||
{
|
||||
if (ancestor == null)
|
||||
{
|
||||
throw new ArgumentNullException("ancestor");
|
||||
}
|
||||
|
||||
if (device != ancestor.device)
|
||||
{
|
||||
throw new ArgumentException("Folders are on different devices");
|
||||
}
|
||||
|
||||
bool hasAncestor = false;
|
||||
if (parentId != 0)
|
||||
{
|
||||
if (parentId == ancestor.FolderId)
|
||||
{
|
||||
hasAncestor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Folder parent = CreateParentFolder();
|
||||
|
||||
hasAncestor = parent.HasAncestor(ancestor);
|
||||
}
|
||||
}
|
||||
return hasAncestor;
|
||||
}
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
MtpDevice.DeleteObject(device.Handle, FolderId);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("{0} (id {1}, parent id {2})", Name, FolderId, ParentId);
|
||||
}
|
||||
|
||||
internal static List<Folder> GetRootFolders(MtpDevice device)
|
||||
{
|
||||
List<Folder> folders = new List<Folder>();
|
||||
IntPtr root = GetFolderList(device.Handle);
|
||||
try
|
||||
{
|
||||
for (IntPtr ptr = root; ptr != IntPtr.Zero;)
|
||||
{
|
||||
FolderStruct folder = (FolderStruct)Marshal.PtrToStructure(ptr, typeof(FolderStruct));
|
||||
folders.Add(new Folder(folder, device));
|
||||
ptr = folder.sibling;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Recursively destroy the folder tree
|
||||
LIBMTP_destroy_folder_t(root);
|
||||
}
|
||||
return folders;
|
||||
}
|
||||
|
||||
internal static uint CreateFolder(MtpDeviceHandle handle, string name, uint parentId)
|
||||
{
|
||||
uint result = LIBMTP_Create_Folder(handle, name, parentId, 0);
|
||||
if (result == 0)
|
||||
{
|
||||
LibMtpException.CheckErrorStack(handle);
|
||||
throw new LibMtpException(ErrorCode.General, "Could not create folder on the device");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static void DestroyFolder(IntPtr folder)
|
||||
{
|
||||
LIBMTP_destroy_folder_t(folder);
|
||||
}
|
||||
|
||||
internal static IntPtr Find(IntPtr folderList, uint folderId)
|
||||
{
|
||||
return LIBMTP_Find_Folder(folderList, folderId);
|
||||
}
|
||||
|
||||
internal static Folder Find(MtpDevice device, uint folderId)
|
||||
{
|
||||
if (device == null)
|
||||
{
|
||||
throw new ArgumentNullException("device");
|
||||
}
|
||||
|
||||
Folder folder = null;
|
||||
IntPtr root = GetFolderList(device.Handle);
|
||||
try
|
||||
{
|
||||
IntPtr ptr = Find(root, folderId);
|
||||
if (ptr != IntPtr.Zero)
|
||||
{
|
||||
FolderStruct folderStruct = (FolderStruct)Marshal.PtrToStructure(ptr, typeof(FolderStruct));
|
||||
folder = new Folder(folderStruct, device);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
DestroyFolder(root);
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
|
||||
internal static IntPtr GetFolderList(MtpDeviceHandle handle)
|
||||
{
|
||||
return LIBMTP_Get_Folder_List(handle);
|
||||
}
|
||||
|
||||
// Folder Management
|
||||
//[DllImport (MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
//private static extern IntPtr LIBMTP_new_folder_t (); // LIBMTP_folder_t*
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void LIBMTP_destroy_folder_t(IntPtr folder);
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_Get_Folder_List(MtpDeviceHandle handle); // LIBMTP_folder_t*
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_Find_Folder(IntPtr folderList, uint folderId); // LIBMTP_folder_t*
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern uint LIBMTP_Create_Folder(MtpDeviceHandle handle, string name, uint parentId, uint storageId);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct FolderStruct
|
||||
{
|
||||
public uint folder_id;
|
||||
public uint parent_id;
|
||||
public uint storage_id;
|
||||
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string name;
|
||||
public IntPtr sibling; // LIBMTP_folder_t*
|
||||
public IntPtr child; // LIBMTP_folder_t*
|
||||
/*
|
||||
public object NextSibling
|
||||
{
|
||||
get
|
||||
{
|
||||
if(sibling == IntPtr.Zero)
|
||||
return null;
|
||||
return (FolderStruct)Marshal.PtrToStructure(sibling, typeof(Folder));
|
||||
}
|
||||
}
|
||||
|
||||
public object NextChild
|
||||
{
|
||||
get
|
||||
{
|
||||
if(child == IntPtr.Zero)
|
||||
return null;
|
||||
return (FolderStruct)Marshal.PtrToStructure(child, typeof(Folder));
|
||||
}
|
||||
}
|
||||
|
||||
public Folder? Sibling
|
||||
{
|
||||
get
|
||||
{
|
||||
if (sibling == IntPtr.Zero)
|
||||
return null;
|
||||
return (Folder)Marshal.PtrToStructure(sibling, typeof(Folder));
|
||||
}
|
||||
}
|
||||
|
||||
public Folder? Child
|
||||
{
|
||||
get
|
||||
{
|
||||
if (child == IntPtr.Zero)
|
||||
return null;
|
||||
return (Folder)Marshal.PtrToStructure(child, typeof(Folder));
|
||||
}
|
||||
}*/
|
||||
|
||||
/*public IEnumerable<Folder> Children()
|
||||
{
|
||||
Folder? current = Child;
|
||||
while(current.HasValue)
|
||||
{
|
||||
yield return current.Value;
|
||||
current = current.Value.Child;
|
||||
}
|
||||
}*/
|
||||
|
||||
/*public IEnumerable<Folder> Siblings()
|
||||
{
|
||||
Folder? current = Sibling;
|
||||
while(current.HasValue)
|
||||
{
|
||||
yield return current.Value;
|
||||
current = current.Value.Sibling;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,642 @@
|
||||
/***************************************************************************
|
||||
* MtpDevice.cs
|
||||
*
|
||||
* Copyright (C) 2006-2007 Alan McGovern
|
||||
* Authors:
|
||||
* Alan McGovern (alan.mcgovern@gmail.com)
|
||||
****************************************************************************/
|
||||
|
||||
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mtp
|
||||
{
|
||||
public delegate int ProgressFunction(ulong sent, ulong total, IntPtr data);
|
||||
|
||||
public class MtpDevice : IDisposable
|
||||
{
|
||||
internal static IntPtr Offset(IntPtr ptr, int offset)
|
||||
{
|
||||
if (IntPtr.Size == 8)
|
||||
{
|
||||
return (IntPtr)(ptr.ToInt64() + offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (IntPtr)(ptr.ToInt32() + offset);
|
||||
}
|
||||
}
|
||||
|
||||
internal MtpDeviceHandle Handle;
|
||||
private MtpDeviceStruct device;
|
||||
private string name;
|
||||
private Folder albumFolder;
|
||||
private Folder musicFolder;
|
||||
private Folder organizerFolder;
|
||||
private Folder pictureFolder;
|
||||
private Folder playlistFolder;
|
||||
private Folder podcastFolder;
|
||||
private Folder textFolder;
|
||||
private Folder videoFolder;
|
||||
|
||||
static MtpDevice()
|
||||
{
|
||||
LIBMTP_Init();
|
||||
}
|
||||
|
||||
public int BatteryLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
ushort level, maxLevel;
|
||||
GetBatteryLevel(Handle, out maxLevel, out level);
|
||||
return (int)((level * 100.0) / maxLevel);
|
||||
}
|
||||
}
|
||||
|
||||
public string SerialNumber
|
||||
{
|
||||
get { return GetSerialnumber(Handle); }
|
||||
}
|
||||
|
||||
public string Version
|
||||
{
|
||||
get { return GetDeviceversion(Handle); }
|
||||
}
|
||||
|
||||
public string ModelName
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
set
|
||||
{
|
||||
if (SetFriendlyName(Handle, value))
|
||||
{
|
||||
name = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Folder AlbumFolder
|
||||
{
|
||||
get { return albumFolder; }
|
||||
}
|
||||
|
||||
public Folder MusicFolder
|
||||
{
|
||||
get { return musicFolder; }
|
||||
}
|
||||
|
||||
public Folder OrganizerFolder
|
||||
{
|
||||
get { return organizerFolder; }
|
||||
}
|
||||
|
||||
public Folder PictureFolder
|
||||
{
|
||||
get { return pictureFolder; }
|
||||
}
|
||||
|
||||
public Folder PlaylistFolder
|
||||
{
|
||||
get { return playlistFolder; }
|
||||
}
|
||||
|
||||
public Folder PodcastFolder
|
||||
{
|
||||
get { return podcastFolder; }
|
||||
}
|
||||
|
||||
public Folder TextFolder
|
||||
{
|
||||
get { return textFolder; }
|
||||
}
|
||||
|
||||
public Folder VideoFolder
|
||||
{
|
||||
get { return videoFolder; }
|
||||
}
|
||||
|
||||
internal MtpDevice(MtpDeviceHandle handle, MtpDeviceStruct device)
|
||||
{
|
||||
this.device = device;
|
||||
this.Handle = handle;
|
||||
this.name = GetFriendlyName(Handle);
|
||||
this.ModelName = GetModelName(Handle);
|
||||
SetDefaultFolders();
|
||||
}
|
||||
|
||||
internal MtpDevice(IntPtr handle, bool ownsHandle, MtpDeviceStruct device)
|
||||
: this(new MtpDeviceHandle(handle, ownsHandle), device)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function scans the top level directories and stores the relevant ones so they are readily
|
||||
/// accessible
|
||||
/// </summary>
|
||||
private void SetDefaultFolders()
|
||||
{
|
||||
List<Folder> folders = GetRootFolders();
|
||||
|
||||
foreach (Folder f in folders)
|
||||
{
|
||||
if (f.FolderId == this.device.default_album_folder)
|
||||
albumFolder = f;
|
||||
else if (f.FolderId == device.default_music_folder)
|
||||
{
|
||||
musicFolder = f;
|
||||
}
|
||||
else if (f.FolderId == device.default_organizer_folder)
|
||||
organizerFolder = f;
|
||||
else if (f.FolderId == device.default_picture_folder)
|
||||
pictureFolder = f;
|
||||
else if (f.FolderId == device.default_playlist_folder)
|
||||
playlistFolder = f;
|
||||
else if (f.FolderId == device.default_text_folder)
|
||||
textFolder = f;
|
||||
else if (f.FolderId == device.default_video_folder)
|
||||
videoFolder = f;
|
||||
else if (f.FolderId == device.default_zencast_folder)
|
||||
podcastFolder = f;
|
||||
}
|
||||
|
||||
// Fix for devices that don't have an explicit playlist folder (see BGO #590342 and #733883)
|
||||
if (playlistFolder == null && musicFolder != null)
|
||||
{
|
||||
playlistFolder = musicFolder;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!Handle.IsClosed)
|
||||
Handle.Close();
|
||||
}
|
||||
|
||||
public List<Folder> GetRootFolders()
|
||||
{
|
||||
return Folder.GetRootFolders(this);
|
||||
}
|
||||
|
||||
public List<Track> GetAllTracks()
|
||||
{
|
||||
return GetAllTracks(null);
|
||||
}
|
||||
|
||||
public List<Track> GetAllTracks(ProgressFunction callback)
|
||||
{
|
||||
IntPtr ptr = Track.GetTrackListing(Handle, callback, IntPtr.Zero);
|
||||
|
||||
List<Track> tracks = new List<Track>();
|
||||
|
||||
while (ptr != IntPtr.Zero)
|
||||
{
|
||||
// Destroy the struct after we use it to avoid potential referencing of freed memory.
|
||||
TrackStruct track = (TrackStruct)Marshal.PtrToStructure(ptr, typeof(TrackStruct));
|
||||
tracks.Add(new Track(track, this));
|
||||
Track.DestroyTrack(ptr);
|
||||
ptr = track.next;
|
||||
}
|
||||
|
||||
return tracks;
|
||||
}
|
||||
|
||||
public List<Playlist> GetPlaylists()
|
||||
{
|
||||
return Playlist.GetPlaylists(this);
|
||||
}
|
||||
|
||||
public List<Album> GetAlbums()
|
||||
{
|
||||
return Album.GetAlbums(this);
|
||||
}
|
||||
|
||||
public List<DeviceStorage> GetStorage()
|
||||
{
|
||||
List<DeviceStorage> storages = new List<DeviceStorage>();
|
||||
IntPtr ptr = device.storage;
|
||||
while (ptr != IntPtr.Zero)
|
||||
{
|
||||
DeviceStorage storage = (DeviceStorage)Marshal.PtrToStructure(ptr, typeof(DeviceStorage));
|
||||
storages.Add(storage);
|
||||
ptr = storage.Next;
|
||||
}
|
||||
return storages;
|
||||
}
|
||||
|
||||
public void Remove(Track track)
|
||||
{
|
||||
DeleteObject(Handle, track.FileId);
|
||||
}
|
||||
|
||||
public void UploadTrack(string path, Track track, Folder folder)
|
||||
{
|
||||
UploadTrack(path, track, folder, null);
|
||||
}
|
||||
|
||||
public void UploadTrack(string path, Track track, Folder folder, ProgressFunction callback)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
throw new ArgumentNullException("path");
|
||||
if (track == null)
|
||||
throw new ArgumentNullException("track");
|
||||
|
||||
folder = folder ?? MusicFolder;
|
||||
if (folder != null)
|
||||
{
|
||||
track.trackStruct.parent_id = folder.FolderId;
|
||||
}
|
||||
|
||||
// We send the trackstruct by ref so that when the file_id gets filled in, our copy is updated
|
||||
Track.SendTrack(Handle, path, ref track.trackStruct, callback, IntPtr.Zero);
|
||||
// LibMtp.GetStorage (Handle, 0);
|
||||
}
|
||||
|
||||
public FileType[] GetFileTypes()
|
||||
{
|
||||
Int16[] ints = GetFileTypes(Handle);
|
||||
FileType[] file_types = new FileType[ints.Length];
|
||||
for (int i = 0; i < ints.Length; i++)
|
||||
{
|
||||
file_types[i] = (FileType)ints[i];
|
||||
}
|
||||
|
||||
return file_types;
|
||||
}
|
||||
|
||||
public static MtpDevice Connect(RawMtpDevice rawDevice)
|
||||
{
|
||||
var raw = rawDevice.RawDevice;
|
||||
IntPtr device = LIBMTP_Open_Raw_Device(raw);
|
||||
if (device == IntPtr.Zero)
|
||||
return null;
|
||||
return new MtpDevice(new MtpDeviceHandle(device, true), (MtpDeviceStruct)Marshal.PtrToStructure(device, typeof(MtpDeviceStruct)));
|
||||
}
|
||||
|
||||
public static List<RawMtpDevice> Detect()
|
||||
{
|
||||
int count = 0;
|
||||
IntPtr ptr = IntPtr.Zero;
|
||||
LIBMTP_Detect_Raw_Devices(ref ptr, ref count);
|
||||
|
||||
List<RawMtpDevice> devices = new List<RawMtpDevice>();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
IntPtr offset = Offset(ptr, i * Marshal.SizeOf(typeof(RawDeviceStruct)));
|
||||
RawDeviceStruct d = (RawDeviceStruct)Marshal.PtrToStructure(offset, typeof(RawDeviceStruct));
|
||||
devices.Add(new RawMtpDevice(d));
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
internal static void ClearErrorStack(MtpDeviceHandle handle)
|
||||
{
|
||||
LIBMTP_Clear_Errorstack(handle);
|
||||
}
|
||||
|
||||
internal static void DeleteObject(MtpDeviceHandle handle, uint object_id)
|
||||
{
|
||||
if (LIBMTP_Delete_Object(handle, object_id) != 0)
|
||||
{
|
||||
LibMtpException.CheckErrorStack(handle);
|
||||
throw new LibMtpException(ErrorCode.General, "Could not delete the track");
|
||||
}
|
||||
}
|
||||
|
||||
internal static void GetBatteryLevel(MtpDeviceHandle handle, out ushort maxLevel, out ushort currentLevel)
|
||||
{
|
||||
int result = LIBMTP_Get_Batterylevel(handle, out maxLevel, out currentLevel);
|
||||
if (result != 0)
|
||||
{
|
||||
LibMtpException.CheckErrorStack(handle);
|
||||
throw new LibMtpException(ErrorCode.General, "Could not retrieve battery stats");
|
||||
}
|
||||
}
|
||||
|
||||
internal static void GetConnectedDevices(out IntPtr list)
|
||||
{
|
||||
Error.CheckError(LIBMTP_Get_Connected_Devices(out list));
|
||||
}
|
||||
|
||||
internal static IntPtr GetErrorStack(MtpDeviceHandle handle)
|
||||
{
|
||||
return LIBMTP_Get_Errorstack(handle);
|
||||
}
|
||||
|
||||
internal static string GetDeviceversion(MtpDeviceHandle handle)
|
||||
{
|
||||
IntPtr ptr = LIBMTP_Get_Deviceversion(handle);
|
||||
if (ptr == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
return StringFromIntPtr(ptr);
|
||||
}
|
||||
|
||||
|
||||
internal static string GetFriendlyName(MtpDeviceHandle handle)
|
||||
{
|
||||
IntPtr ptr = LIBMTP_Get_Friendlyname(handle);
|
||||
if (ptr == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
return StringFromIntPtr(ptr);
|
||||
}
|
||||
|
||||
internal static bool SetFriendlyName(MtpDeviceHandle handle, string name)
|
||||
{
|
||||
bool success = LIBMTP_Set_Friendlyname(handle, name) == 0;
|
||||
return success;
|
||||
}
|
||||
|
||||
internal static string GetModelName(MtpDeviceHandle handle)
|
||||
{
|
||||
IntPtr ptr = LIBMTP_Get_Modelname(handle);
|
||||
if (ptr == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
return StringFromIntPtr(ptr);
|
||||
}
|
||||
|
||||
internal static string GetSerialnumber(MtpDeviceHandle handle)
|
||||
{
|
||||
IntPtr ptr = LIBMTP_Get_Serialnumber(handle);
|
||||
if (ptr == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
return StringFromIntPtr(ptr);
|
||||
}
|
||||
|
||||
internal static void GetStorage(MtpDeviceHandle handle, int sortMode)
|
||||
{
|
||||
LIBMTP_Get_Storage(handle, sortMode);
|
||||
}
|
||||
|
||||
internal static Int16[] GetFileTypes(MtpDeviceHandle handle)
|
||||
{
|
||||
IntPtr types = IntPtr.Zero;
|
||||
ushort count = 0;
|
||||
if (LIBMTP_Get_Supported_Filetypes(handle, ref types, ref count) == 0)
|
||||
{
|
||||
Int16[] type_ary = new Int16[count];
|
||||
Marshal.Copy(types, type_ary, 0, (int)count);
|
||||
Marshal.FreeHGlobal(types);
|
||||
return type_ary;
|
||||
}
|
||||
|
||||
return new Int16[0];
|
||||
}
|
||||
|
||||
internal static void ReleaseDevice(IntPtr handle)
|
||||
{
|
||||
LIBMTP_Release_Device(handle);
|
||||
}
|
||||
|
||||
private static string StringFromIntPtr(IntPtr ptr)
|
||||
{
|
||||
int i = 0;
|
||||
while (Marshal.ReadByte(ptr, i) != (byte)0) ++i;
|
||||
byte[] s_buf = new byte[i];
|
||||
Marshal.Copy(ptr, s_buf, 0, s_buf.Length);
|
||||
string s = System.Text.Encoding.UTF8.GetString(s_buf);
|
||||
Marshal.FreeCoTaskMem(ptr);
|
||||
return s;
|
||||
}
|
||||
|
||||
internal const string LibMtpLibrary = "libmtp.dll";
|
||||
|
||||
// Device Management
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void LIBMTP_Init();
|
||||
|
||||
// Clears out the error stack and frees any allocated memory.
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void LIBMTP_Clear_Errorstack(MtpDeviceHandle handle);
|
||||
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern int LIBMTP_Delete_Object(MtpDeviceHandle handle, uint object_id);
|
||||
|
||||
// Gets the first connected device:
|
||||
//[DllImport (LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
//private static extern IntPtr LIBMTP_Get_First_Device (); // LIBMTP_mtpdevice_t *
|
||||
|
||||
// Gets the storage information
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int LIBMTP_Get_Storage(MtpDeviceHandle handle, int sortMode);
|
||||
|
||||
// Formats the supplied storage device attached to the device
|
||||
//[DllImport (LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
//private static extern int LIBMTP_Format_Storage (MtpDeviceHandle handle, ref DeviceStorage storage);
|
||||
|
||||
// Counts the devices in the list
|
||||
//[DllImport (LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
//private static extern uint LIBMTP_Number_Devices_In_List (MtpDeviceHandle handle);
|
||||
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern ErrorCode LIBMTP_Get_Connected_Devices(out IntPtr list); //LIBMTP_mtpdevice_t **
|
||||
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern ErrorCode LIBMTP_Detect_Raw_Devices(ref IntPtr list, ref int count); //LIBMTP_raw_device_t
|
||||
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_Open_Raw_Device(RawDeviceStruct rawdevice);
|
||||
|
||||
// Deallocates the memory for the device
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void LIBMTP_Release_Device(IntPtr device);
|
||||
|
||||
//[DllImport (LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
//private static extern int LIBMTP_Reset_Device (MtpDeviceHandle handle);
|
||||
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int LIBMTP_Get_Batterylevel(MtpDeviceHandle handle, out ushort maxLevel, out ushort currentLevel);
|
||||
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_Get_Modelname(MtpDeviceHandle handle); // char *
|
||||
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_Get_Serialnumber(MtpDeviceHandle handle); // char *
|
||||
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_Get_Deviceversion(MtpDeviceHandle handle); // char *
|
||||
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_Get_Friendlyname(MtpDeviceHandle handle); // char *
|
||||
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int LIBMTP_Set_Friendlyname(MtpDeviceHandle handle, string name);
|
||||
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_Get_Errorstack(MtpDeviceHandle handle); // LIBMTP_error_t *
|
||||
|
||||
[DllImport(LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int LIBMTP_Get_Supported_Filetypes(MtpDeviceHandle handle, ref IntPtr types, ref ushort count); // uint16_t **const
|
||||
|
||||
|
||||
// void LIBMTP_Release_Device_List (LIBMTP_mtpdevice_t *)
|
||||
|
||||
|
||||
// int LIBMTP_Detect_Descriptor (uint16_t *, uint16_t *);
|
||||
/*
|
||||
void LIBMTP_Dump_Device_Info (LIBMTP_mtpdevice_t *)
|
||||
|
||||
char * LIBMTP_Get_Syncpartner (LIBMTP_mtpdevice_t *)
|
||||
int LIBMTP_Set_Syncpartner (LIBMTP_mtpdevice_t *, char const *const)
|
||||
int LIBMTP_Get_Secure_Time (LIBMTP_mtpdevice_t *, char **const)
|
||||
int LIBMTP_Get_Device_Certificate (LIBMTP_mtpdevice_t *, char **const)
|
||||
*/
|
||||
|
||||
public static string GetMimeTypeFor(FileType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case FileType.MP3: return "audio/mpeg";
|
||||
case FileType.OGG: return "audio/ogg";
|
||||
case FileType.WMA: return "audio/x-ms-wma";
|
||||
case FileType.WMV: return "video/x-ms-wmv";
|
||||
case FileType.ASF: return "video/x-ms-asf";
|
||||
case FileType.AAC: return "audio/x-aac";
|
||||
case FileType.MP4: return "video/mp4";
|
||||
case FileType.AVI: return "video/avi";
|
||||
case FileType.WAV: return "audio/x-wav";
|
||||
case FileType.MPEG: return "video/mpeg";
|
||||
case FileType.FLAC: return "audio/flac";
|
||||
case FileType.QT: return "video/quicktime";
|
||||
case FileType.M4A: return "audio/mp4";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct DeviceEntry
|
||||
{
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string vendor;
|
||||
public ushort vendor_id;
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string product;
|
||||
public ushort product_id;
|
||||
public uint device_flags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DeviceStorage
|
||||
{
|
||||
public uint Id;
|
||||
public ushort StorageType;
|
||||
public ushort FileSystemType;
|
||||
public ushort AccessCapability;
|
||||
public ulong MaxCapacity;
|
||||
public ulong FreeSpaceInBytes;
|
||||
public ulong FreeSpaceInObjects;
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string StorageDescription;
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string VolumeIdentifier;
|
||||
public IntPtr Next; // LIBMTP_devicestorage_t*
|
||||
public IntPtr Prev; // LIBMTP_devicestorage_t*
|
||||
}
|
||||
|
||||
internal class MtpDeviceHandle : SafeHandle
|
||||
{
|
||||
private MtpDeviceHandle()
|
||||
: base(IntPtr.Zero, true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal MtpDeviceHandle(IntPtr ptr, bool ownsHandle)
|
||||
: base(IntPtr.Zero, ownsHandle)
|
||||
{
|
||||
SetHandle(ptr);
|
||||
}
|
||||
|
||||
public override bool IsInvalid
|
||||
{
|
||||
get { return handle == IntPtr.Zero; }
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
MtpDevice.ReleaseDevice(handle);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
internal struct MtpDeviceStruct
|
||||
{
|
||||
public byte object_bitsize;
|
||||
public IntPtr parameters; // void*
|
||||
public IntPtr usbinfo; // void*
|
||||
public IntPtr storage; // LIBMTP_devicestorage_t*
|
||||
public IntPtr errorstack; // LIBMTP_error_t*
|
||||
public byte maximum_battery_level;
|
||||
public uint default_music_folder;
|
||||
public uint default_playlist_folder;
|
||||
public uint default_picture_folder;
|
||||
public uint default_video_folder;
|
||||
public uint default_organizer_folder;
|
||||
public uint default_zencast_folder;
|
||||
public uint default_album_folder;
|
||||
public uint default_text_folder;
|
||||
public IntPtr cd; // void*
|
||||
public IntPtr next; // LIBMTP_mtpdevice_t*
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct RawDeviceStruct
|
||||
{
|
||||
public DeviceEntry device_entry; /**< The device entry for this raw device */
|
||||
public uint bus_location; /**< Location of the bus, if device available */
|
||||
public byte devnum; /**< Device number on the bus, if device available */
|
||||
}
|
||||
|
||||
public class RawMtpDevice
|
||||
{
|
||||
|
||||
public uint BusNumber
|
||||
{
|
||||
get { return RawDevice.bus_location; }
|
||||
}
|
||||
|
||||
public int DeviceNumber
|
||||
{
|
||||
get { return RawDevice.devnum; }
|
||||
}
|
||||
|
||||
internal RawDeviceStruct RawDevice
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
internal RawMtpDevice(RawDeviceStruct device)
|
||||
{
|
||||
RawDevice = device;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,145 @@
|
||||
/***************************************************************************
|
||||
* Playlist.cs
|
||||
*
|
||||
* Copyright (C) 2006-2007 Alan McGovern
|
||||
* Authors:
|
||||
* Alan McGovern (alan.mcgovern@gmail.com)
|
||||
****************************************************************************/
|
||||
|
||||
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mtp
|
||||
{
|
||||
public sealed class Playlist : AbstractTrackList
|
||||
{
|
||||
internal static List<Playlist> GetPlaylists(MtpDevice device)
|
||||
{
|
||||
List<Playlist> playlists = new List<Playlist>();
|
||||
IntPtr ptr = Playlist.LIBMTP_Get_Playlist_List(device.Handle);
|
||||
while (ptr != IntPtr.Zero)
|
||||
{
|
||||
// Destroy the struct *after* we use it to ensure we don't access freed memory
|
||||
// for the 'tracks' variable
|
||||
PlaylistStruct d = (PlaylistStruct)Marshal.PtrToStructure(ptr, typeof(PlaylistStruct));
|
||||
playlists.Add(new Playlist(device, d));
|
||||
LIBMTP_destroy_playlist_t(ptr);
|
||||
ptr = d.next;
|
||||
}
|
||||
return playlists;
|
||||
}
|
||||
|
||||
private PlaylistStruct playlist;
|
||||
|
||||
public override uint Count
|
||||
{
|
||||
get { return playlist.no_tracks; }
|
||||
protected set { playlist.no_tracks = value; }
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return playlist.Name; }
|
||||
set { playlist.Name = value; }
|
||||
}
|
||||
|
||||
protected override IntPtr TracksPtr
|
||||
{
|
||||
get { return playlist.tracks; }
|
||||
set { playlist.tracks = value; }
|
||||
}
|
||||
|
||||
public Playlist(MtpDevice device, string name) : base(device)
|
||||
{
|
||||
this.playlist = new PlaylistStruct();
|
||||
Name = name;
|
||||
Count = 0;
|
||||
}
|
||||
|
||||
internal Playlist(MtpDevice device, PlaylistStruct playlist) : base(device, playlist.tracks, playlist.no_tracks)
|
||||
{
|
||||
// Once we've loaded the tracks, set the TracksPtr to NULL as it
|
||||
// will be freed when the Playlist constructor is finished.
|
||||
this.playlist = playlist;
|
||||
TracksPtr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
protected override int Create()
|
||||
{
|
||||
playlist.parent_id = Device.PlaylistFolder.FolderId;
|
||||
return LIBMTP_Create_New_Playlist(Device.Handle, ref playlist);
|
||||
}
|
||||
|
||||
protected override int Update()
|
||||
{
|
||||
return LIBMTP_Update_Playlist(Device.Handle, ref playlist);
|
||||
}
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
MtpDevice.LIBMTP_Delete_Object(Device.Handle, playlist.playlist_id);
|
||||
}
|
||||
|
||||
// Playlist Management
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void LIBMTP_destroy_playlist_t(IntPtr playlist);
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_Get_Playlist_List(MtpDeviceHandle handle); // LIBMTP_playlist_t*
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int LIBMTP_Create_New_Playlist(MtpDeviceHandle handle, ref PlaylistStruct metadata);
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int LIBMTP_Update_Playlist(MtpDeviceHandle handle, ref PlaylistStruct playlist);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct PlaylistStruct
|
||||
{
|
||||
public uint playlist_id;
|
||||
public uint parent_id;
|
||||
public uint storage_id;
|
||||
|
||||
[MarshalAs(UnmanagedType.LPStr)]
|
||||
public string Name;
|
||||
|
||||
public IntPtr tracks; // int*
|
||||
public uint no_tracks;
|
||||
public IntPtr next; // LIBMTP_playlist_t*
|
||||
|
||||
|
||||
/*public Playlist? Next
|
||||
{
|
||||
get
|
||||
{
|
||||
if (next == IntPtr.Zero)
|
||||
return null;
|
||||
return (Playlist)Marshal.PtrToStructure(next, typeof(Playlist));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,344 @@
|
||||
/***************************************************************************
|
||||
* Track.cs
|
||||
*
|
||||
* Copyright (C) 2006-2007 Alan McGovern
|
||||
* Authors:
|
||||
* Alan McGovern (alan.mcgovern@gmail.com)
|
||||
****************************************************************************/
|
||||
|
||||
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Mtp
|
||||
{
|
||||
public class Track
|
||||
{
|
||||
internal TrackStruct trackStruct;
|
||||
private MtpDevice device;
|
||||
|
||||
public uint FileId
|
||||
{
|
||||
get { return trackStruct.item_id; }
|
||||
}
|
||||
|
||||
public string Album
|
||||
{
|
||||
get { return trackStruct.album; }
|
||||
set { trackStruct.album = value; }
|
||||
}
|
||||
|
||||
public string Artist
|
||||
{
|
||||
get { return trackStruct.artist; }
|
||||
set { trackStruct.artist = value; }
|
||||
}
|
||||
|
||||
public uint Bitrate
|
||||
{
|
||||
get { return trackStruct.bitrate; }
|
||||
}
|
||||
|
||||
public ushort BitrateType
|
||||
{
|
||||
get { return trackStruct.bitratetype; }
|
||||
}
|
||||
|
||||
public string ReleaseDate
|
||||
{
|
||||
get { return trackStruct.date; }
|
||||
set { trackStruct.date = value; }
|
||||
}
|
||||
|
||||
public int Year
|
||||
{
|
||||
get { return ReleaseDate == null || ReleaseDate.Length < 4 ? 0 : Int32.Parse(ReleaseDate.Substring(0, 4)); }
|
||||
set { ReleaseDate = String.Format("{0:0000}0101T0000.00", value); }
|
||||
}
|
||||
|
||||
public uint Duration
|
||||
{
|
||||
get { return trackStruct.duration; }
|
||||
set { trackStruct.duration = value; }
|
||||
}
|
||||
|
||||
public string FileName
|
||||
{
|
||||
get { return trackStruct.filename; }
|
||||
set { trackStruct.filename = value; }
|
||||
}
|
||||
|
||||
public ulong FileSize
|
||||
{
|
||||
get { return trackStruct.filesize; }
|
||||
set { trackStruct.filesize = value; }
|
||||
}
|
||||
|
||||
public FileType FileType
|
||||
{
|
||||
get { return trackStruct.filetype; }
|
||||
set { trackStruct.filetype = value; }
|
||||
}
|
||||
|
||||
public string Genre
|
||||
{
|
||||
get { return trackStruct.genre; }
|
||||
set { trackStruct.genre = value; }
|
||||
}
|
||||
|
||||
public ushort NoChannels
|
||||
{
|
||||
get { return trackStruct.nochannels; }
|
||||
set { trackStruct.nochannels = value; }
|
||||
}
|
||||
|
||||
// 0 to 100
|
||||
public ushort Rating
|
||||
{
|
||||
get { return trackStruct.rating; }
|
||||
set
|
||||
{
|
||||
if (value < 0 || value > 100)
|
||||
throw new ArgumentOutOfRangeException("Rating", "Rating must be between zero and 100");
|
||||
trackStruct.rating = value;
|
||||
}
|
||||
}
|
||||
|
||||
public uint SampleRate
|
||||
{
|
||||
get { return trackStruct.samplerate; }
|
||||
set { trackStruct.samplerate = value; }
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get { return trackStruct.title; }
|
||||
set { trackStruct.title = value; }
|
||||
}
|
||||
|
||||
public ushort TrackNumber
|
||||
{
|
||||
get { return trackStruct.tracknumber; }
|
||||
set { trackStruct.tracknumber = value; }
|
||||
}
|
||||
|
||||
public uint WaveCodec
|
||||
{
|
||||
get { return trackStruct.wavecodec; }
|
||||
}
|
||||
|
||||
public uint UseCount
|
||||
{
|
||||
get { return trackStruct.usecount; }
|
||||
set { trackStruct.usecount = value; }
|
||||
}
|
||||
|
||||
public string Composer
|
||||
{
|
||||
get { return trackStruct.composer; }
|
||||
set { trackStruct.composer = value; }
|
||||
}
|
||||
|
||||
public Track(string filename, ulong filesize) : this(filename, filesize, null)
|
||||
{
|
||||
}
|
||||
|
||||
public Track(string filename, ulong filesize, MtpDevice device) : this(new TrackStruct(), device)
|
||||
{
|
||||
this.trackStruct.filename = filename;
|
||||
this.trackStruct.filesize = filesize;
|
||||
this.trackStruct.filetype = DetectFileType(this);
|
||||
}
|
||||
|
||||
internal Track(TrackStruct track, MtpDevice device)
|
||||
{
|
||||
this.device = device;
|
||||
this.trackStruct = track;
|
||||
}
|
||||
|
||||
public bool InFolder(Folder folder)
|
||||
{
|
||||
return InFolder(folder, false);
|
||||
}
|
||||
|
||||
public bool InFolder(Folder folder, bool recursive)
|
||||
{
|
||||
if (folder == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_parent = trackStruct.parent_id == folder.FolderId;
|
||||
if (is_parent || !recursive)
|
||||
{
|
||||
return is_parent;
|
||||
}
|
||||
|
||||
return Folder.Find(device, trackStruct.parent_id).HasAncestor(folder);
|
||||
}
|
||||
|
||||
public void Download(string path)
|
||||
{
|
||||
Download(path, null);
|
||||
}
|
||||
|
||||
public void Download(string path, ProgressFunction callback)
|
||||
{
|
||||
if (String.IsNullOrEmpty(path))
|
||||
throw new ArgumentException("Cannot be null or empty", "path");
|
||||
|
||||
GetTrack(device.Handle, trackStruct.item_id, path, callback, IntPtr.Zero);
|
||||
}
|
||||
|
||||
public void UpdateMetadata()
|
||||
{
|
||||
UpdateTrackMetadata(device.Handle, ref trackStruct);
|
||||
}
|
||||
|
||||
private static FileType DetectFileType(Track track)
|
||||
{
|
||||
string ext = System.IO.Path.GetExtension(track.FileName);
|
||||
|
||||
// Strip leading .
|
||||
if (ext.Length > 0)
|
||||
ext = ext.Substring(1, ext.Length - 1);
|
||||
|
||||
// this is a hack; catch all m4(a|b|v|p)
|
||||
if (ext != null && ext.ToLower().StartsWith("m4"))
|
||||
ext = "mp4";
|
||||
|
||||
FileType type = (FileType)Enum.Parse(typeof(FileType), ext, true);
|
||||
//if (type == null)
|
||||
// return FileType.UNKNOWN;
|
||||
return type;
|
||||
}
|
||||
|
||||
internal static void DestroyTrack(IntPtr track)
|
||||
{
|
||||
LIBMTP_destroy_track_t(track);
|
||||
}
|
||||
|
||||
internal static void GetTrack(MtpDeviceHandle handle, uint trackId, string destPath, ProgressFunction callback, IntPtr data)
|
||||
{
|
||||
if (LIBMTP_Get_Track_To_File(handle, trackId, destPath, callback, data) != 0)
|
||||
{
|
||||
LibMtpException.CheckErrorStack(handle);
|
||||
throw new LibMtpException(ErrorCode.General, "Could not download track from the device");
|
||||
}
|
||||
}
|
||||
|
||||
internal static IntPtr GetTrackListing(MtpDeviceHandle handle, ProgressFunction function, IntPtr data)
|
||||
{
|
||||
return LIBMTP_Get_Tracklisting_With_Callback(handle, function, data);
|
||||
}
|
||||
|
||||
internal static void SendTrack(MtpDeviceHandle handle, string path, ref TrackStruct metadata, ProgressFunction callback, IntPtr data)
|
||||
{
|
||||
if (LIBMTP_Send_Track_From_File(handle, path, ref metadata, callback, data) != 0)
|
||||
{
|
||||
LibMtpException.CheckErrorStack(handle);
|
||||
throw new LibMtpException(ErrorCode.General, "Could not upload the track");
|
||||
}
|
||||
}
|
||||
|
||||
internal static void UpdateTrackMetadata(MtpDeviceHandle handle, ref TrackStruct metadata)
|
||||
{
|
||||
if (LIBMTP_Update_Track_Metadata(handle, ref metadata) != 0)
|
||||
throw new LibMtpException(ErrorCode.General);
|
||||
}
|
||||
|
||||
//[DllImport (MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
//private static extern IntPtr LIBMTP_new_track_t (); // LIBMTP_track_t *
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void LIBMTP_destroy_track_t(IntPtr track); // LIBMTP_track_t *
|
||||
|
||||
//[DllImport (MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
//private static extern IntPtr LIBMTP_Get_Tracklisting (MtpDeviceHandle handle); //LIBMTP_track_t *
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr LIBMTP_Get_Tracklisting_With_Callback(MtpDeviceHandle handle, ProgressFunction callback, IntPtr data); // LIBMTP_track_t *
|
||||
|
||||
//[DllImport (MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
//private static extern IntPtr LIBMTP_Get_Trackmetadata (MtpDeviceHandle handle, uint trackId); // LIBMTP_track_t *
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int LIBMTP_Get_Track_To_File(MtpDeviceHandle handle, uint trackId, string path, ProgressFunction callback, IntPtr data);
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int LIBMTP_Send_Track_From_File(MtpDeviceHandle handle, string path, ref TrackStruct track, ProgressFunction callback, IntPtr data);
|
||||
|
||||
[DllImport(MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int LIBMTP_Update_Track_Metadata(MtpDeviceHandle handle, ref TrackStruct metadata);
|
||||
|
||||
//[DllImport (MtpDevice.LibMtpLibrary, CallingConvention = CallingConvention.Cdecl)]
|
||||
//private static extern int LIBMTP_Track_Exists (MtpDeviceHandle handle, uint trackId);
|
||||
|
||||
//int LIBMTP_Get_Track_To_File_Descriptor (MtpDeviceHandle handle, uint trackId, int const, LIBMTP_progressfunc_t const, void const *const)
|
||||
//int LIBMTP_Send_Track_From_File_Descriptor (MtpDeviceHandle handle, int const, LIBMTP_track_t *const, LIBMTP_progressfunc_t const, void const *const, uint32_t const)
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct TrackStruct
|
||||
{
|
||||
public uint item_id;
|
||||
public uint parent_id;
|
||||
public uint storage_id;
|
||||
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string title;
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string artist;
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string composer;
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string genre;
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string album;
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string date;
|
||||
[MarshalAs(UnmanagedType.LPStr)] public string filename;
|
||||
|
||||
public ushort tracknumber;
|
||||
public uint duration;
|
||||
public uint samplerate;
|
||||
public ushort nochannels;
|
||||
public uint wavecodec;
|
||||
public uint bitrate;
|
||||
public ushort bitratetype;
|
||||
public ushort rating; // 0 -> 100
|
||||
public uint usecount;
|
||||
public ulong filesize;
|
||||
#if LIBMTP_SIZEOF_TIME_T_64
|
||||
public ulong modificationdate;
|
||||
#else
|
||||
public uint modificationdate;
|
||||
#endif
|
||||
public FileType filetype;
|
||||
public IntPtr next; // Track Null if last
|
||||
/*
|
||||
public Track? Next
|
||||
{
|
||||
get
|
||||
{
|
||||
if (next == IntPtr.Zero)
|
||||
return null;
|
||||
return (Track)Marshal.PtrToStructure(next, typeof(Track));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
//
|
||||
// MyClass.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2019 Mike Becker
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UniversalEditor.IO;
|
||||
|
||||
namespace UniversalEditor.Accessors.MTP
|
||||
{
|
||||
public class MTPAccessor : Accessor
|
||||
{
|
||||
private static AccessorReference _ar = null;
|
||||
|
||||
protected override void InitializeInternal()
|
||||
{
|
||||
base.InitializeInternal();
|
||||
}
|
||||
|
||||
public override long Length { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
public override void Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override void CloseInternal()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override long GetPosition()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected override AccessorReference MakeReferenceInternal()
|
||||
{
|
||||
if (_ar == null)
|
||||
{
|
||||
_ar = base.MakeReferenceInternal();
|
||||
_ar.Title = "Media Transfer Protocol (MTP)";
|
||||
_ar.Schemas.Add("mtp-disabled");
|
||||
_ar.ImportOptions.Add(new CustomOptionText("FileName", "File _name"));
|
||||
}
|
||||
return _ar;
|
||||
}
|
||||
|
||||
private static IntPtr Offset(IntPtr ptr, int offset)
|
||||
{
|
||||
if (IntPtr.Size == 8)
|
||||
{
|
||||
return (IntPtr)(ptr.ToInt64() + offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (IntPtr)(ptr.ToInt32() + offset);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OpenInternal()
|
||||
{
|
||||
/*
|
||||
List<Mtp.RawMtpDevice> list = Mtp.MtpDevice.Detect();
|
||||
Mtp.RawMtpDevice rawdev = list[0];
|
||||
Mtp.MtpDevice dev = Mtp.MtpDevice.Connect(rawdev);
|
||||
|
||||
List<Mtp.Folder> listFolders = dev.GetRootFolders();
|
||||
*/
|
||||
// int w = Internal.Methods.Get_File_To_File(hRawDevice, 0, OriginalUri.LocalPath, null, IntPtr.Zero);
|
||||
|
||||
// IntPtr hFile = Internal.Linux.Methods.g_file_new_for_uri(OriginalUri.OriginalString);
|
||||
}
|
||||
|
||||
protected override int ReadInternal(byte[] buffer, int start, int count)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override int WriteInternal(byte[] buffer, int start, int count)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
//
|
||||
// AssemblyInfo.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2019 Mike Becker
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("UniversalEditor.Plugins.MTP")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("Mike Becker")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{EA724755-2670-4520-86AA-657C8A124DB7}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>UniversalEditor</RootNamespace>
|
||||
<AssemblyName>UniversalEditor.Plugins.MTP</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\..\Output\Debug\Plugins</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\..\Output\Release\Plugins</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Accessors\MTP\MTPAccessor.cs" />
|
||||
<Compile Include="Accessors\MTP\LibMTP\File.cs" />
|
||||
<Compile Include="Accessors\MTP\LibMTP\FileType.cs" />
|
||||
<Compile Include="Accessors\MTP\LibMTP\AbstractTrackList.cs" />
|
||||
<Compile Include="Accessors\MTP\LibMTP\Album.cs" />
|
||||
<Compile Include="Accessors\MTP\LibMTP\ErrorCode.cs" />
|
||||
<Compile Include="Accessors\MTP\LibMTP\FileSampleData.cs" />
|
||||
<Compile Include="Accessors\MTP\LibMTP\Folder.cs" />
|
||||
<Compile Include="Accessors\MTP\LibMTP\MtpDevice.cs" />
|
||||
<Compile Include="Accessors\MTP\LibMTP\Playlist.cs" />
|
||||
<Compile Include="Accessors\MTP\LibMTP\Error.cs" />
|
||||
<Compile Include="Accessors\MTP\LibMTP\Track.cs" />
|
||||
<Compile Include="Accessors\MTP\Internal\Linux\Methods.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Libraries\UniversalEditor.Core\UniversalEditor.Core.csproj">
|
||||
<Project>{2D4737E6-6D95-408A-90DB-8DFF38147E85}</Project>
|
||||
<Name>UniversalEditor.Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Accessors\" />
|
||||
<Folder Include="Accessors\MTP\" />
|
||||
<Folder Include="Accessors\MTP\LibMTP\" />
|
||||
<Folder Include="Accessors\MTP\Internal\" />
|
||||
<Folder Include="Accessors\MTP\Internal\Linux\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@ -141,6 +141,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins.Printing", "Plugins
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalEditor.Plugins.Generic.Printing", "Plugins.Printing\UniversalEditor.Plugins.Generic.Printing\UniversalEditor.Plugins.Generic.Printing.csproj", "{A3231B32-A0E4-4B67-9A09-310B25BBB9B6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalEditor.Plugins.MTP", "Plugins\UniversalEditor.Plugins.MTP\UniversalEditor.Plugins.MTP.csproj", "{EA724755-2670-4520-86AA-657C8A124DB7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -405,6 +407,10 @@ Global
|
||||
{A3231B32-A0E4-4B67-9A09-310B25BBB9B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A3231B32-A0E4-4B67-9A09-310B25BBB9B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A3231B32-A0E4-4B67-9A09-310B25BBB9B6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EA724755-2670-4520-86AA-657C8A124DB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EA724755-2670-4520-86AA-657C8A124DB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EA724755-2670-4520-86AA-657C8A124DB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EA724755-2670-4520-86AA-657C8A124DB7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{6F0AB1AF-E1A1-4D19-B19C-05BBB15C94B2} = {05D15661-E684-4EC9-8FBD-C014BA433CC5}
|
||||
@ -470,6 +476,7 @@ Global
|
||||
{242A32D8-9A3A-4FE3-902B-AB9C3154723A} = {05D15661-E684-4EC9-8FBD-C014BA433CC5}
|
||||
{868A6888-EDB9-407E-A710-40F297D4EAB8} = {0399182F-AF56-4E86-B229-EAB38C2EE6AF}
|
||||
{A3231B32-A0E4-4B67-9A09-310B25BBB9B6} = {FB678C6D-29A0-405B-BA86-E1EC12A96AA9}
|
||||
{EA724755-2670-4520-86AA-657C8A124DB7} = {2ED32D16-6C06-4450-909A-40D32DA67FB4}
|
||||
EndGlobalSection
|
||||
GlobalSection(MonoDevelopProperties) = preSolution
|
||||
Policies = $0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user