diff --git a/RMuseum/Models/GanjoorAudio/AudioSyncStatus.cs b/RMuseum/Models/GanjoorAudio/AudioSyncStatus.cs
new file mode 100644
index 00000000..c03c33ca
--- /dev/null
+++ b/RMuseum/Models/GanjoorAudio/AudioSyncStatus.cs
@@ -0,0 +1,39 @@
+namespace RMuseum.Models.GanjoorAudio
+{
+ ///
+ /// Audio Synchronization Status (binary combination is acceptable)
+ ///
+ public enum AudioSyncStatus
+ {
+ ///
+ /// no changed
+ ///
+ Synchronized = 0,
+
+ ///
+ /// new upload
+ ///
+ NewItem = 1,
+
+ ///
+ /// meta data should be updated
+ ///
+ MetadataChanged = 2,
+
+ ///
+ /// sound files should be reuploaded
+ ///
+ SoundFilesChanged = 4,
+
+ ///
+ /// Xml file should be reuploaded
+ ///
+ XmlFileChanged = 8,
+
+ ///
+ /// Item is deleted
+ ///
+ Deleted = 16
+
+ }
+}
diff --git a/RMuseum/Models/GanjoorAudio/PoemNarration.cs b/RMuseum/Models/GanjoorAudio/PoemNarration.cs
new file mode 100644
index 00000000..fa074e5d
--- /dev/null
+++ b/RMuseum/Models/GanjoorAudio/PoemNarration.cs
@@ -0,0 +1,152 @@
+using RSecurityBackend.Models.Auth.Db;
+using System;
+
+
+namespace RMuseum.Models.GanjoorAudio
+{
+ ///
+ /// Poem Narration
+ ///
+ public class PoemNarration
+ {
+ ///
+ /// Id
+ ///
+ public Guid Id { get; set; }
+
+ ///
+ /// Owner User
+ ///
+ public RAppUser Owner { get; set; }
+
+ ///
+ /// Owner User Id
+ ///
+ public Guid OwnerId { get; set; }
+
+ ///
+ /// Ganjoor Post Id
+ ///
+ public int GanjoorPostId { get; set; }
+
+ ///
+ /// This determines where an audio is displayed between a list of sounds related to a specfic poem
+ ///
+ public int AudioOrder { get; set; }
+
+ ///
+ /// Final data is actually exported to a MySQL database which this auto increment field is its key
+ ///
+ public int GanjoorAudioId { get; set; }
+
+ ///
+ /// Using this field content you would determine xml, mp3 and ogg file names
+ ///
+ public string FileNameWithoutExtension { get; set; }
+
+ ///
+ /// combining this with + .ext would preduce relative path of sound files on our file server the full path would become [HOMEPath] + '/i/' + this value
+ ///
+ ///
+ /// "a2"
+ ///
+ ///
+ /// We had previously used different pathes because when a directory became overcrowded our connection time would increase unbearably due to IRAN internet problems, so it is sensible to store it per record and not as a global option value
+ ///
+ public string SoundFilesFolder { get; set; }
+
+ ///
+ /// MP3 File Path
+ ///
+ public string Mp3FilePath { get { return $"/i/{SoundFilesFolder}/{FileNameWithoutExtension}.mp3"; } }
+
+ ///
+ /// MP3 url
+ ///
+ public string Mp3Url { get { return $"https://i.ganjoor.net/{SoundFilesFolder}/{FileNameWithoutExtension}.mp3"; } }
+
+
+ ///
+ /// OGG File Path
+ ///
+ public string OggFilePath { get { return $"/i/{SoundFilesFolder}/{FileNameWithoutExtension}.ogg"; } }
+
+ ///
+ /// OGG url
+ ///
+ public string OggUrl { get { return $"https://i.ganjoor.net/{SoundFilesFolder}/{FileNameWithoutExtension}.ogg"; } }
+
+ ///
+ /// This is also a legacy field
+ ///
+ ///
+ /// "/i/a2/x"
+ ///
+ public string XMLFilePath { get { return $"/i/{SoundFilesFolder}/x/{FileNameWithoutExtension}.xml"; } }
+
+ ///
+ /// Audio Title
+ ///
+ public string AudioTitle { get; set; }
+
+ ///
+ /// Audio Artist
+ ///
+ public string AudioArtist { get; set; }
+
+ ///
+ /// Audio Artist Url
+ ///
+ public string AudioArtistUrl { get; set; }
+
+ ///
+ /// Audio Source
+ ///
+ public string AudioSrc { get; set; }
+
+ ///
+ /// Audio Src Url
+ ///
+ public string AudioSrcUrl { get; set; }
+
+ ///
+ /// Legacy Audio Guid
+ ///
+ public Guid LegacyAudioGuid { get; set; }
+
+ ///
+ /// Audio File CheckSum
+ ///
+ public string Mp3FileCheckSum { get; set; }
+
+ ///
+ /// mp3 size in bytes
+ ///
+ public int Mp3SizeInBytes { get; set; }
+
+ ///
+ /// ogg size in bytes
+ ///
+ public int OggSizeInBytes { get; set; }
+
+ ///
+ /// Audio Date
+ ///
+ public DateTime UploadDate { get; set; }
+
+ ///
+ /// MP3 File temporary pass on Windows Server
+ ///
+ public string TemporaryUploadedMp3FilePath { get; set; }
+
+ ///
+ /// XML File temporary pass on Windows Server
+ ///
+ public string TemporaryUploadedXmlFilePath { get; set; }
+
+ ///
+ /// Value is one or a combination of
+ ///
+ public int AudioSyncStatus { get; set; }
+ }
+}
diff --git a/RMuseum/RMuseum.xml b/RMuseum/RMuseum.xml
index f44a4d22..b2f7c194 100644
--- a/RMuseum/RMuseum.xml
+++ b/RMuseum/RMuseum.xml
@@ -1495,6 +1495,185 @@
User Note
+
+
+ Audio Synchronization Status (binary combination is acceptable)
+
+
+
+
+ no changed
+
+
+
+
+ new upload
+
+
+
+
+ meta data should be updated
+
+
+
+
+ sound files should be reuploaded
+
+
+
+
+ Xml file should be reuploaded
+
+
+
+
+ Item is deleted
+
+
+
+
+ Poem Narration
+
+
+
+
+ Id
+
+
+
+
+ Owner User
+
+
+
+
+ Owner User Id
+
+
+
+
+ Ganjoor Post Id
+
+
+
+
+ This determines where an audio is displayed between a list of sounds related to a specfic poem
+
+
+
+
+ Final data is actually exported to a MySQL database which this auto increment field is its key
+
+
+
+
+ Using this field content you would determine xml, mp3 and ogg file names
+
+
+
+
+ combining this with + .ext would preduce relative path of sound files on our file server the full path would become [HOMEPath] + '/i/' + this value
+
+
+ "a2"
+
+
+ We had previously used different pathes because when a directory became overcrowded our connection time would increase unbearably due to IRAN internet problems, so it is sensible to store it per record and not as a global option value
+
+
+
+
+ MP3 File Path
+
+
+
+
+ MP3 url
+
+
+
+
+ OGG File Path
+
+
+
+
+ OGG url
+
+
+
+
+ This is also a legacy field
+
+
+ "/i/a2/x"
+
+
+
+
+ Audio Title
+
+
+
+
+ Audio Artist
+
+
+
+
+ Audio Artist Url
+
+
+
+
+ Audio Source
+
+
+
+
+ Audio Src Url
+
+
+
+
+ Legacy Audio Guid
+
+
+
+
+ Audio File CheckSum
+
+
+
+
+ mp3 size in bytes
+
+
+
+
+ ogg size in bytes
+
+
+
+
+ Audio Date
+
+
+
+
+ MP3 File temporary pass on Windows Server
+
+
+
+
+ XML File temporary pass on Windows Server
+
+
+
+
+ Value is one or a combination of
+
+
ganjoor link for artifacts and items