Request for comments: Plugin-Interface für DLNA-Plugin

  • Hi, wie in diversen Threads angekündigt, hat das neue DLNA-Plugin, ebenfalls eine Plugin-Schnittstelle, um die Profile und ResourceProvider anzubinden. Ziel des ganzen ist es, die Komplexität des restlichen Codes drastisch zu verringern und die Möglichkeit zu bieten, eigene Anbindungen einzubringen.


    Da das Thema ziemlich komplex ist und ich nicht in eine falsche Richtung entwickeln möchte, würde ich gerne von euch, die Schnittstelle bewerten lassen.


    Die Schnittstelle ist als Anhang beigefügt. Es sind Kommentare an den wichtigsten Funktionen beigefügt, um den Sinn der Funktion zu erklären. Ich hoffe, dass sie aussagekräftig genug sind.


    Da das Interesse am UPnP/DLNA-Plugin offensichtlich wieder steigt, hoffe ich, dass sich der eine oder andere findet, der Kritik daran äußert.

    Files

    • plugin.h.txt

      (16.2 kB, downloaded 148 times, last: )


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

  • Hi,
    habe mir jetzt nur die Metadata Klasse angesehen, dazu ein paar Ideen, über die man natürlich geteilter Meinung sein kann.


    (0. ich find Ungarische Notation für Klassennamen doof, aber ich weiß, dass das VDR Coding Stil ist *fg*)


    1. string cMetadata::Property::operator()() -- würde mir überlegen, ob ich das nicht lieber weglasse. Die Property enthält ja zwei Strings, Key und Value, und ich meine es wäre saubererer (und selbstdokumentierender) Code, auf diese auch explizit zuzugreifen.


    2. cMetadata::AddProperty() und cMetaData::SetProperty() -- könnte ich mir Überladungen mit string key, string/long/bool value vorstellen, als "convenience". Die Semantik bei cMetaData::SetProperty() müsste dafür natürlich genau geklärt sein (alle existierenden mit dem Key weg, nur den ersten überschreiben, ...?)


    3. cMetaData::SetParentID() und cMetaData::SetParentID() -- sind nur für die Persistenz da, richtig? Ich glaube nicht, dass sie dann ins objektorientierte Interface gehören -- da würde ich eher Dinge erwarten wie Get/SetParent() und Get/Set/AddChildren().


    4. Title, UpnpClass, Restricted, Description usw sind wie ich das verstehe "well-known properties". Sollte man die nicht auch als cMetadata::Property ablegen, mit als const definierten Keys (public const string cMetadata::Property::TITLE = "Title"; sowas ...)? Dann wäre es jedenfalls ausgeschlossen, dass jemand eine zusätzliche Property "Title" einführt, die dann als etwas anderes interpretiert wird.


    Wie gesagt, nur Vorschläge -- kann sein dass die auch gar nicht gut sind, dazu kenne ich die Materie viel zu wenig :)

    Asrock A75 Pro4-M
    Debian wheezy (testing, stock) (aktuell 2012-08-24: Linux 3.2, VDR 1.7.28)
    vdr-sxfe (xineliboutput)
    Pioneer VSX-520-K

  • (0. ich find Ungarische Notation für Klassennamen doof, aber ich weiß, dass das VDR Coding Stil ist *fg*)


    Als Ungar lasse mich es mal so formulieren: diese "Idee" hättest Du Dir sparen können. ;)


    Albert

  • 1. string cMetadata::Property::operator()() -- würde mir überlegen, ob ich das nicht lieber weglasse. Die Property enthält ja zwei Strings, Key und Value, und ich meine es wäre saubererer (und selbstdokumentierender) Code, auf diese auch explizit zuzugreifen.


    Das ist eine Altlast, ich nutze die gar nicht, weil ich wenn dann meist über Iteratoren gehe und da sieht (*it)() irgendwie scheiße aus. Kommt weg.


    2. cMetadata::AddProperty() und cMetaData::SetProperty() -- könnte ich mir Überladungen mit string key, string/long/bool value vorstellen, als "convenience". Die Semantik bei cMetaData::SetProperty() müsste dafür natürlich genau geklärt sein (alle existierenden mit dem Key weg, nur den ersten überschreiben, ...?)


    Okay, müsste man noch weiter ausdiskutieren.


    3. cMetaData::SetParentID() und cMetaData::SetParentID() -- sind nur für die Persistenz da, richtig? Ich glaube nicht, dass sie dann ins objektorientierte Interface gehören -- da würde ich eher Dinge erwarten wie Get/SetParent() und Get/Set/AddChildren().


    Ich kann/möchte eigentlich die Baumstruktur nicht direkt im Objekt drin haben, da ich Angst habe, dass ich den gleichen Fehler mache, wie beim letzten Plugin. Dort fehlte mir ein geeigneter Cache, der nach der ersten Ebene aufhört weitere Objekte zu laden. Am Ende hatte ich den gesamten Objektbaum im RAM und die Anwendung hat Minuten zum Starten gebraucht. Ich habe gestern abend aber noch zwei weitere Funktionen eingeführt: SetObjectIDByUri(string uri) und SetParentIDByUri(string uri). Die ObjectID/ParentID ist letztlich nur eine UUID V.5 mit URL-Namensraum. Damit müsste die Eindeutigkeit gewährleistet sein und ein Plugin muss sich auch nicht um die Generierung der IDs Gedanken machen.


    4. Title, UpnpClass, Restricted, Description usw sind wie ich das verstehe "well-known properties". Sollte man die nicht auch als cMetadata::Property ablegen, mit als const definierten Keys (public const string cMetadata::Property::TITLE = "Title"; sowas ...)? Dann wäre es jedenfalls ausgeschlossen, dass jemand eine zusätzliche Property "Title" einführt, die dann als etwas anderes interpretiert wird.


    hmm.. so hatte ich es erst. Da aber die Klasse cMetadata in etwa die gleiche Struktur hat, wie die SQLite-Tabellen, weiß ich dann nicht, wie ich eine Suche über diese Felder durchführe. Es war auch so Gedacht, dass die wichtigsten Felder über Getter/Setter schnell erreichbar sind, wobei die theoretisch hinten heraus in die gleiche Datenstruktur schreiben und lesen könnten. Hmm.. wie gesagt, wenn mir jemand erklärt, wie ich die Property-Liste effizient in eine Datenbank pressen, aber immer noch über die Felder eine SQL-Suche durchführen kann, wäre die Idee auch nicht sooo blöd.


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

  • hmm.. so hatte ich es erst. Da aber die Klasse cMetadata in etwa die gleiche Struktur hat, wie die SQLite-Tabellen, weiß ich dann nicht, wie ich eine Suche über diese Felder durchführe. Es war auch so Gedacht, dass die wichtigsten Felder über Getter/Setter schnell erreichbar sind, wobei die theoretisch hinten heraus in die gleiche Datenstruktur schreiben und lesen könnten. Hmm.. wie gesagt, wenn mir jemand erklärt, wie ich die Property-Liste effizient in eine Datenbank pressen, aber immer noch über die Felder eine SQL-Suche durchführen kann, wäre die Idee auch nicht sooo blöd.


    Also ich würde ja einfach mal sagen: Es gibt keinen zwingenden Grund, die Struktur in Tabellen 1:1 in Objekten nachzubilden (oder umgekehrt). Die Persistenzschicht muss sowieso Daten kopieren und Objekte anlegen, dabei kann auch die Struktur verändert werden, und Tabellen sind eben was anderes als Objekte (passt auch zu der Frage Objektgraph oder Sammlung von Objekten mit IDs).


    Aber letztlich ist es natürlich ein Implementierungsdetail (das ist jetzt der "Fehler" von C++, dass es am Interface ÜBERHAUPT erkennbar wird, wie du es machst). Du kannst natürlich auch mit anderen Mitteln verhindern, dass GetPropertyByKey("Title").GetValue() etwas anderes liefert als GetTitle(). Auf jeden Fall (egal wie es nun intern aussieht) fände ich string-Konstanten für die "well-known properties" sinnvoll.

    Asrock A75 Pro4-M
    Debian wheezy (testing, stock) (aktuell 2012-08-24: Linux 3.2, VDR 1.7.28)
    vdr-sxfe (xineliboutput)
    Pioneer VSX-520-K

  • Die Properties in der Datenbank sind einfach.


    Dafür brauchst du eine Zweite Tabelle der Key ist der Key der Metadaten + die Property.
    Dann kannst mit SQL schön suchen, einfügen, löschen, alle Properties eines Datensatzes usw.


    Johns

    Sag mir, wo die Developer sind. Wo sind sie geblieben? . . . . . . . . . . . . . . . . . . . . SoftHdDevice - A software and GPU emulated HD output device plugin.
    Sag mir, wo die Developer sind. Was ist geschehn?


    Client0: Crown CW02 MSI_C847MS-E33 Zotac_GT640_passiv Cine-S2 iMon-MCE / streamdev softhddevice
    Client1: Lian_Li_PC-Q09FB ASRock_H67M-ITX/HT I3-2100 ASUS_ENGT520_passiv / streamdev softhddevice
    Test: Lian_Li_PC-Q09R Asus C60M1-I / streamdev
    Server0: Dockstar TT-S2-3600-USB / streamdev
    Server2: Lian_Li_PC-Q07R Intel_DH61DL G620 WD20EARX 90W PicoPSU Cine-S2+DuoFlex-S2+DuoFlex-CT / streamdev / 22 Watt Verbrauch

  • Die Properties in der Datenbank sind einfach.


    Dafür brauchst du eine Zweite Tabelle der Key ist der Key der Metadaten + die Property.
    Dann kannst mit SQL schön suchen, einfügen, löschen, alle Properties eines Datensatzes usw.


    Johns


    Kannst du mir eine Beispiel-Tabelle mit Suche machen?


    Meine Key-Value-Tabelle sieht so aus:


    SQL
    1. CREATE TABLE properties (
    2. ObjectID TEXT REFERENCES objects.ObjectID,
    3. Property TEXT NOT NULL,
    4. Value TEXT
    5. );


    Wie suche ich jetzt zu einem bestimmten Objekt im Titel oder der Beschreibung, wenn diese als Properties in der Key-Value-Liste gespeichert worden?


    Aber letztlich ist es natürlich ein Implementierungsdetail (das ist jetzt der "Fehler" von C++, dass es am Interface ÜBERHAUPT erkennbar wird, wie du es machst). Du kannst natürlich auch mit anderen Mitteln verhindern, dass GetPropertyByKey("Title").GetValue() etwas anderes liefert als GetTitle(). Auf jeden Fall (egal wie es nun intern aussieht) fände ich string-Konstanten für die "well-known properties" sinnvoll.


    Okay, kann ich tun, wenn sich mir die obige Frage erschließt. Ich fände es auch wegen der Datenhaltung effizienter, wenn es nur Key-Value-Paare gibt, wo ALLES gespeichert wird, anstatt Key-Value + Well-Known-Properties daneben.


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

  • Bin nicht mehr fitt mit SQL, aber im Prinzip müsste es so gehen.


    Eine Property holen:

    SQL
    1. SELECT `Value` FROM `properties` WHERE `ObjectID`=ID AND `Property`="Title";


    Alle Properties holen:

    SQL
    1. SELECT `Value` FROM `properties` WHERE `ObjectID`=ID;


    Edit: besser: Alle Properties holen:

    SQL
    1. SELECT `Property`,`Value` FROM `properties` WHERE `ObjectID`=ID;



    Johns

    Sag mir, wo die Developer sind. Wo sind sie geblieben? . . . . . . . . . . . . . . . . . . . . SoftHdDevice - A software and GPU emulated HD output device plugin.
    Sag mir, wo die Developer sind. Was ist geschehn?


    Client0: Crown CW02 MSI_C847MS-E33 Zotac_GT640_passiv Cine-S2 iMon-MCE / streamdev softhddevice
    Client1: Lian_Li_PC-Q09FB ASRock_H67M-ITX/HT I3-2100 ASUS_ENGT520_passiv / streamdev softhddevice
    Test: Lian_Li_PC-Q09R Asus C60M1-I / streamdev
    Server0: Dockstar TT-S2-3600-USB / streamdev
    Server2: Lian_Li_PC-Q07R Intel_DH61DL G620 WD20EARX 90W PicoPSU Cine-S2+DuoFlex-S2+DuoFlex-CT / streamdev / 22 Watt Verbrauch

    The post was edited 1 time, last by johns ().

  • Hi methodus,


    ich kenne Deinen background nicht, aber so geht das nicht :O
    Mein alter Meister (18hundert vor dem Krieg) hätte gesagt: Du zäumst das Pferd vom Schwanz auf.
    UPnP und DLNA sind Schnittstellen-Spezifikationen. Dein Datenmodel und Deine innere Struktur (Schnittstelle für Plugins) haben damit aber so garnichts mit zu tun.
    Wenn Du Dir Dein Datenmodel von Schnittstellen diktieren lässt, dann hast Du eine Abhängigkeit, die nicht sein müsste und meist geht es dann mächtig in die Hose.


    Du willst doch ein Plugin für den VDR schreiben - da kann man zumindest erwarten, dass Du Dir mal Code vom Autor himself reinziehst. Damit Du ein Gefühl dafür bekommst, was wie weshalb warum gemacht wird.
    ... und für mich gehört es zum Mindestmaß an Respekt, dass man sich an die Gepflogenheiten des Original-Autors hält - egal, ob man das mag oder nicht.
    Aber ok, vielleicht bin ich da etwas zu altmodisch - zu meiner Zeit hat Respekt noch zum guten Ton gehört.


    Will sagen:
    Einmal wird im VDR anders formatiert und dann verwendet Klaus die postfix-Notation mit 3 Slashes von doxygen für Kommentare.
    Was ich aber als den größten Fehler ansehe:
    Der VDR ist kompakt geschrieben, mit Blick auf Effizienz und wenig Speicherverbrauch.
    Wenn ich mir da anschaue, wie großzügig Du mit int32 umgehst - ohne nachzudenken und ohne Not.
    Hm, das sieht für mich nicht so aus, als hättest Du viel Erfahrung in C-Programmierung.


    Also schau dir mal die Wertebereiche der Zahlendatentypen an.
    Die Anzahl an Audiokanälen passt locker in einen char-Datentyp (0 - 256 unsigned, bzw. bis 127 signed - reicht auch noch ewig)
    Wenn Du einen numerischen Funktionsparameter brauchst, ist int das performanteste. also lieber dann in der Funktion konvertieren. Die Konvertierung von Ganzzahlen kleiner int nach int macht der Compiler implizit. Nur andersherum brauchst Du nen cast.


    Bei der sample-Frequenz kann man davon ausgehen, dass die in kHz angegeben wird, bzw. man kann sich selbst darauf festlegen.
    Wenn Du also an der Stelle ein short nehmen würdest, könntest Du sogar eine Nachkommastelle berücksichtigen und hättest immer noch genügend Platz.


    Dann ist es im VDR so, dass die Getter kein 'Get'-Prefix haben.
    Wenn eine Klasse ein Attribut Beispiel hätte, dann würde das so aussehen:

    Code
    1. class Test {
    2. private:
    3. char *beispiel;
    4. public:
    5. char *Beispiel(void) { return beispiel; }
    6. void SetBeispiel(const char *Beispiel);
    7. };

    Ein Setter hat weder bei VDR noch sonstwo einen Rückgabewert. Eine Funktion mit Rückgabewert ist teurer und sicher kein Setter mehr.
    Wenn Du nicht möchtest, dass Anwender Deiner Klasse den Getter mistbrauchen, kannst Du es auch so kodieren:


    Auch wenn ich Deine Reihenfolge der Zugriffsabschnitte richtig finde, sie ist nicht richtig im VDR-Umfeld, da Klaus den privaten Bereich oben haben will.
    Dem sollte Dein Plugin auch folgen, also: erst private, dann protected und zum Schluss public


    Dann finde ich geschachtelte Klassen für eine Schnittstelle eher ungeschickt und kontraproduktiv.


    Eine Schnittstelle soll doch 2 Parteien unabhängiger von einander machen, sodass jeder sein Ding machen kann.
    Das bedeutet aber auch, dass eine Schnittstelle so einfach wie möglich sein soll und dass sie langlebig sein soll - was heißt, jeder kann seinen Code an geänderte Anforderungen anpassen ohne die andere Partei zu zwingen, alles neu übersetzen zu müssen.


    Ich finde, Du solltest das Standardwerk erstmal zuklappen und Dir klar werden, was Du möchtest.
    Mit Abgrenzungen und geplanten Erweiterungen, was andere Entwickler später beisteuern sollen und wie das (technisch) bewerkstelligt werden kann.


    Bitte mistversteh es jetzt nicht wieder als Werbung, aber schau Dir mal an, wie ich die Medien in CMP verwaltet habe.
    Ich habe dort 10 Resource-Typen und möchte auf keinen verzichten. Zum Abspielen werden sie dann wie eine einzige Resource behandelt. Von außen kein Unterschied.
    Derzeit habe ich die Dateitypen noch hartkodiert - die werden noch rausgezogen in Beschreibungsdateien, sodass der Anwender die Liste nach seinen Vorstellungen anpassen kann.


    Für eine UPnP/DLNA-Schnittstelle könnte ich die Typen wieder auf eine Schnittstellenklasse reduzieren, aber das ist eine andere Geschichte.
    Zum Erfassen und Bearbeiten der Attribute möchte ich unterschiedliche Resourcen haben.
    Wenn Du Dein Vorhaben mal von der Datenseite betrachtest, wirst Du auch Unterschiede feststellen, die es sicher wert sind, berücksichtigt zu werden.
    Transformation für Schnittstellen ist dann ein anderes Thema.


    Dann würde ich Dir empfehlen, mach Dir erstmal einen Prototypen.
    Dazu kannst Du Dir eine eigene main stricken und den VDR als Bibliothek einbinden.
    So kannst Du alles erstmal auf einer Spielwiese ausprobieren und wenn dann alles läuft, kannst Du Dein Plugin in den VDR integrieren.
    Wenn Dein Prototyp läuft, wäre auch der richtige Zeitpunkt, über Schnittstellen nachzudenken.


    Ich habe für CMP netbeans verwendet. Damit kann man Prototypen entwickeln.
    Per Drag&Drop können Dateien zwischen Bibliothek und Hauptproggy oder zwischen einer Bibliothek und einer anderen verschoben werden.
    Wenn einem der ganze Wust an Nebensächlichkeiten mal abgenommen wird, kann man sich auf sein Thema konzentrieren und richtig produktiv werden :)


    Gruß Gero

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

  • Hi Geronimo,


    ich habe selten so einen Bull-Sh*t gelesen wie du jetzt gerade fabriziert hast. Sorry, aber ich habe nach einer ernst gemeinten Meinung gefragt und nicht gefordert, dass meine Programmierfähigkeiten in Frage gestellt werden. Bei so einem angehäuften Blödsinn, muss ich mir die Frage stellen, ob ich mir die Arbeit machen soll, das Plugin für Leute wie dich anzubieten, oder es unter Verschluss zu halten und nur privat zu nutzen. Ich kann mir das Plugin auch so stricken, wie ich es brauche und es dabei belassen. Dann kann ICH per DLNA Live-TV und Aufnahmen streamen und auch spulen, dann kann ICH mir jederzeit Erweiterungen schreiben, um andere Dateien, wie MP3s anzubieten.


    Nur um ein paar Gründe für die Design-Entscheidungen zu machen: wenn die Spezifikation die Datentypen vorgibt, nehme ich diese Datentypen. Es ist mir vollkommen egal, ob die long oder short für die Anzahl der Audiokanäle nehmen. Die Schnittstelle ist so definiert. Deswegen ist es ein STANDARD geworden. Eine Schnittstellenspezifikation! Ich habe keine Ahnung über deinen Background, aber in meiner Welt ist eine Schnittstellenspezifikation ein Gesetz, ob ich das INTERN weiterverwende, ist meine Sache. EXTERN MUSS ich es so anbieten.


    Es ist kein Wunder, dass du mit deinen Versuchen deine Server zum Laufen zu bekommen, ständig scheiterst. Die hier gebrachten Äußerungen bestäigen das mehr als deutlich.


    Zu meiner Zeit hatte man noch Respekt gezollt, wenn sich überhaupt jemand mit einem Thema in seiner Freizeit beschäftigt hat und hat die Ergebnisse auch gewürdigt, selbst wenn sie nicht optimal waren. Eine weitere Diskussion auf einem so niedrigem Niveau kann und muss ich mir echt verbitten.


    Zum Thema zurück:


    johns : Ich tu mich manchmal mit SQL-Selects schwer. Angenommen ich möchte alle Pflichtparameter eines Objects selektieren, dann wäre es ja so:


    SQL
    1. SELECT `Value` FROM `properties` WHERE `ObjectID`=ID AND `Property`="Title" OR `Property`="Description" OR `Property`="Class" OR ...


    Jetzt habe ich jede Menge Zeilen, die ich transponieren muss. Ich denke mal der Effizienzgewinn wird dadurch wieder hinfällig gemacht.


    Als zweites Beispiel, wo ich keine Ahnung habe ist: Wenn ich nach einem bestimmten Titel und einer bestimmten Klasse suchen möchte, dann müsste es ja so aussehen:

    SQL
    1. SELECT `Value` FROM `properties` WHERE (`Property`="Title" AND Value="Hello World") OR `Property`="Description" OR (`Property`="Class" AND Value="object.item")


    Die Abfragen werden dadurch enorm komplex und die Transponierung muss trotzdem noch stattfinden. Ich bin mir da ziemlich unsicher, ob das so effektiv sein soll.


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin


  • Bitte zusammenarbeiten und Kritik nicht böse nehmen. Und auf keinen Fall beleidigt sein.
    Es gibt immer welche die berechtigt oder nicht berechtig meckern und wenn man OpenSource macht muß man damit leben.
    Wenn es Reaktionen auf OpenSource gibt, dann ist es meistens negative bzw. Wünsche.
    Positive gibt es aber auch und man sollte nur diese ernst nehmen.


    Die Abfragen macht der SQL Server und der macht die meist sehr effektiv.
    Wobei ich mir am Anfang keine Gedanken über Effektivität machen würde.
    Erst kommt die Funktion und wenn alles funktioniert kann man benchmarken und optimieren.


    SQL
    1. SELECT `Property`,`Value` FROM `properties` WHERE `ObjectID`=ID AND `Property`="Title" OR `Property`="Description" OR `Property`="Class" OR ...


    Hier fehlt noch Property, damit du die Paare Property und Value hast. Die meiste Zeit geht bei mysql für die Befehlsübertragung drauf.
    Ob du dann 1 Datensatz oder 10 Datensätze bekommst spielt dann keine Rolle mehr.


    Das wollte ich schon letzesmal dazuschreiben, du solltest noch ein paar Keys anlegen. Damit der Zugriff schneller wird.
    1 Key ist (ObjectID, Property) als primary key und dann vielleicht noch nur die ObjectID.


    SQL
    1. SELECT `ObjectID` FROM `properties` WHERE (`Property`="Title" AND Value="Hello World") OR `Property`="Description" OR (`Property`="Class" AND Value="object.item")


    Du wirst hier die ObjectID haben wollen und nicht den Wert.


    MySQL kann auch Strings in Werten suchen usw. du kannst sehr komplexe Anfragen bauen, die komplett in SQL abgearbeitet werden.
    Sqlite hat einen geringeren Umfang und ist auch nicht so performant.


    Schau das etwas fertig ist, dann mach mal ein paar Tests mit 100000 Datensätzen.
    Zur Not mußt du dann etwas in C/C++ cachen.


    Johns

    Sag mir, wo die Developer sind. Wo sind sie geblieben? . . . . . . . . . . . . . . . . . . . . SoftHdDevice - A software and GPU emulated HD output device plugin.
    Sag mir, wo die Developer sind. Was ist geschehn?


    Client0: Crown CW02 MSI_C847MS-E33 Zotac_GT640_passiv Cine-S2 iMon-MCE / streamdev softhddevice
    Client1: Lian_Li_PC-Q09FB ASRock_H67M-ITX/HT I3-2100 ASUS_ENGT520_passiv / streamdev softhddevice
    Test: Lian_Li_PC-Q09R Asus C60M1-I / streamdev
    Server0: Dockstar TT-S2-3600-USB / streamdev
    Server2: Lian_Li_PC-Q07R Intel_DH61DL G620 WD20EARX 90W PicoPSU Cine-S2+DuoFlex-S2+DuoFlex-CT / streamdev / 22 Watt Verbrauch

  • Stimmt. Mein Fehler, "Don't feed the troll".


    Okay. Da ich das mit den SQL-Statements selbst nicht leisten kann, bräuchte ich an dieser Stelle imense Hilfe. Meine Kenntnisse mit SQL sind mehrere Jahre zurück und hab nahezu alles wieder vergessen. Also wer sich beteiligen möchte, immer zu!


    Ein anderes Thema: hat sich schon jemand die eigentliche Schnittstelle der Plugins angesehen? Das erste soll eine Schnittstelle zu einem Dateisystem oder ähnlichem bereitstellen und das zweite soll es ermöglichen für jedes Profil oder Profilgruppe einen eigenen Parser zu schreiben.


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

  • Okay, ich könnte jetzt zunächst folgenden Kompromiss anbieten, so lange ich mit den SQL-Statements noch kämpf:


    - Die Klasse Property fällt weg. Stattdessen werden die Getter und Setter in die Metadata-Klasse verschoben. Bei SetProperty gibt es den optionalen Parameter Index. Dieser ist standardmäßig 0. Wenn es mehrere Properties mit gleichen Namen gibt, wird nur der erste geändert oder der mit dem angegebenen Index.
    - Die Resource-Klasse bleibt bestehen. Wenn ich die auch in die Metadata-Klasse schieben würde, hätte ich keine 1:N-Beziehung mehr.
    - Die Datenbankstruktur bleibt zunächst erstmal. Es ist für mich momentan einfacher. Wenn sich jemand findet, der das verbessern möchte, kann sich ja melden.


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

  • Der VDR ist kompakt geschrieben, mit Blick auf Effizienz und wenig Speicherverbrauch.
    Wenn ich mir da anschaue, wie großzügig Du mit int32 umgehst - ohne nachzudenken und ohne Not.
    Hm, das sieht für mich nicht so aus, als hättest Du viel Erfahrung in C-Programmierung.


    Also schau dir mal die Wertebereiche der Zahlendatentypen an.
    Die Anzahl an Audiokanälen passt locker in einen char-Datentyp (0 - 256 unsigned, bzw. bis 127 signed - reicht auch noch ewig)
    Wenn Du einen numerischen Funktionsparameter brauchst, ist int das performanteste. also lieber dann in der Funktion konvertieren. Die Konvertierung von Ganzzahlen kleiner int nach int macht der Compiler implizit. Nur andersherum brauchst Du nen cast.


    Ohne den Thread jetzt ZU sehr aufzublähen, aber zumindest das ist ausgemachter Quatsch. Erstens mal ist "wenig Speicherverbrauch" nicht automatisch effizient, wenn man dafür dann unterschiedliche Werte in einem Wort mühevoll "auseinanderklamüsern" muss wo man sie ansonsten (bei gescheitem alignment) sehr effizient in Datenregister laden könnte. Was interessiert dich mehr, eine Handvoll "verschwendete" Bytes in einer Datenstruktur (bei RAM-Größen von mehreren GB) oder verschwendete Rechenzyklen in einem tight loop? Zweitens: Nein, nicht "int" ist das performanteste sondern das native Wort des Systems. Das wäre auf AMD64 ein 64bit-Wort (z.B. int64_t). Bei GCC hat man aber entschieden, dass int auch auf AMD64 einem 32bit-Wort entspricht. "int" ist meistens das performanteste, aber eben nicht immer.


    edit: Ich MUSS auch was zum Coding-Stil sagen. Mir stößt schon, wie schon erwähnt, diese ungarische Notation in der VDR codebase übel auf. Das macht heute keiner mehr. es hilft nicht fürs Verständnis und verunstaltet die Namen mit sinnlosen Zusatz-Buchstaben. Auch andere Dinge gefallen mir nicht. Wenn ich direkt an einer Codebase arbeite (sagen wir, ich würde einen Patch für VDR bauen) -- dann halte ich mich selbstverständlich GANZ genau an den bereits vorhandenen Stil. Hab ich bei mutt gemacht (keine Ahnung, was ich seinerzeit daran "gepatcht" habe) -- würd ich bei jedem anderen OSS Projekt machen. ABER: Ein Plugin ist was anderes ... das hat ne klar definierte Schnittstelle, die es einzuhalten gilt. Der Rest ist allein MEINE SACHE, als Entwickler. Wenn am Ende was besser lesbares rauskommt als der original VDR Code -- mir soll es recht sein. /edit

    Asrock A75 Pro4-M
    Debian wheezy (testing, stock) (aktuell 2012-08-24: Linux 3.2, VDR 1.7.28)
    vdr-sxfe (xineliboutput)
    Pioneer VSX-520-K

    The post was edited 1 time, last by zirias ().

  • Quote

    Was interessiert dich mehr, eine Handvoll "verschwendete" Bytes in einer Datenstruktur (bei RAM-Größen von mehreren GB) oder verschwendete Rechenzyklen in einem tight loop?


    Wenn Du mal Software für embedded System geschrieben hast, bei denen es auf jedes verbrauchte Byte ankommt, dann würdest Du anders reden.
    Wenn der VDR nur für fette PCs entwickelt wäre, ließe er sich nicht so einfach auf kleine System portieren.
    Aber dazu müsste man schon bereit sein, übern Tellerrand hinaus zu schauen, bzw. sich mit der Arbeit anderer auseinander zu setzen.


    Mir stößt es auf, wenn Möchtegern-Experten von Optimierung reden, aber nichtmal einen Benchmark geschrieben haben.
    z.B. was kostet der Einsatz von PropertyMaps an Speicher und Laufzeit und wo liegt ein möglicher Gewinn.
    Ein kleines Testproggy kann das schnell beantworten.


    oder:
    wenn ich in meiner Struktur 2 Byte einspare sind das bei geplanten 50.000 Datensätzen im Speicher ...


    oder:
    wie groß ist der Unterschied, wenn ich Datenstrukturen des VDR verwende, bzw. um wieviel wird der VDR aufgebläht, wenn ich neue Bibliotheken dazu linke.


    Es gibt viele Stellen, an denen man Vor- und Nachteile gegenüberstellen kann und sich fragen müsste, ist es das wert, was ich gerade vorhabe?
    Kann ich das gleiche vielleicht auch auf anderem Wege erreichen?


    Quote

    Mir stößt schon, wie schon erwähnt, diese ungarische Notation in der VDR codebase übel auf


    Nun, wenn Du die Irrwege der ungarischen Notation in den Anfangstagen von Windows, OS/2 etc. mitbekommen hättest, dann wäre Dir klar, dass im VDR keine ungarische Notation verwendet wird.


    Mach einfach mal einen kleinen Versuch:
    Eine Klasse A hat ein Attribut der Klasse B
    Jetzt schreib mal die Klasse A mit Getter und Setter ohne irgendeine Art von Prefix oder Postfix zu verwenden und schau, was Dein Compiler dazu meint.
    Das hat sicher auch dazu beigetragen, dass im VDR Methoden groß geschrieben werden. Dass Klaus sich dafür entschieden hat, eine Klasse mit kleinem 'c' anfangen zu lassen, hat sich als äußerst hilfreich erwiesen. Beim Verständnis genauso, wie bei der Fehlersuche. Ist also wesentlich besser, als ein Unterstrich oder andere künstliche Konstrukte.


    ... und wer sich mal mit QS beschäftigt hat, weiß, dass Codeformatierung ein wichtiges Qualitätsmerkmal ist (für mich ist die Formatierung, die Klaus erfand, das Beste, was mir je begegnet ist. Man braucht etwas, um reinzukommen, aber der Gewinn an Lesbarkeit ist unerreicht).
    Nicht umsonst gibt es in jedem größeren Projekt Styleguides und Codierungsrichtlinien. Das ist im Opensource-Bereich genauso gültig, wie in größeren Software-Unternehmen.
    ... und da Menschen eben unterschiedlich sind, sind es auch fast alle Styleguides und Codierungsrichtlinien.
    Der Projektverantwortliche legt fest, was für sein Projekt gilt - und nur das entscheidet über richtig und falsch.
    Der Geschmack eines Programmierers ist völlig irrelevant.


    Wer das nicht sehen will, muss erstmal erwachsen werden.



    Gruß Gero

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

  • Moin!


    SQL
    1. SELECT `Property`,`Value` FROM `properties` WHERE `ObjectID`=ID AND `Property`="Title" OR `Property`="Description" OR `Property`="Class" OR ...


    Ich weiß jetzt nicht genau, was dieser Select liefern soll, aber bei Kombination von AND und OR muss man eventuell auch Klammern benutzen. Ich benutze gerne lieber eine Klammer zu viel, damit deutlich wird, wie der Ausdruck zu verstehen ist.
    AND ist "höher" als OR, d.h. das Statement wird interpretiert als:

    SQL
    1. SELECT `Property`,`Value` FROM `properties` WHERE (`ObjectID`=ID AND `Property`="Title") OR `Property`="Description" OR `Property`="Class" OR ...


    War das Ergebnis die Absicht? Oder sollte das hier herauskommen:

    SQL
    1. SELECT `Property`,`Value` FROM `properties` WHERE `ObjectID`=ID AND (`Property`="Title" OR `Property`="Description" OR `Property`="Class" OR ...)


    (ich hoffe, ich irre mich nicht...) :)


    In meiner Praxiserfahrung gibt es drei grobe Stufen, die ein Programm durchlaufen muss:

    • es funktioniert, d.h. es liefert das Ergebnis, das gewünscht ist
    • es funktioniert schnell (genug), und liefert immer noch das richtige Ergebnis
    • es funktioniert schnell und resourcenschonend (und natürlich immer noch mit dem richtigen Ergebnis)


    Solange der erste Punkt nicht erfüllt ist, braucht sich um die folgenden noch nicht kümmern. Das kommt alles noch früh genug.
    Und das darf dann auch ein komplettes Neuschreiben der Software beinhalten, wo das ganze Erlernte dann einfließt. :)


    Zum Thema "lesbarer Code": das ist Geschmackssache, da gibt es keinen "besten" Stil, da jeder das etwas anders sieht. Den Stil, den wir hier in der Firma pflegen, sieht in vielen Details anders aus, als in den meisten (Linux-)OSS-Projekten. Für mich ist das aber der "am besten lesbare" Stil, weil ich den am meisten lese. Und letztendlich gibt es dafür Programme, die die Formatierung anpassen können. Wenn ich Source sehe, der für mich "unlesbar" geschrieben ist, dann jage ich ihn durch "indent" o.ä. und gut ist. Formatierung ist wichtig, aber nicht entscheidend.


    Es wäre schön, wenn es jetzt erst mal um Punkt 1 geht, alles danach ist (noch) irrelevant. Denn ich bin ein potientieller Nutzer dieses Plugins und möchte, dass es veröffentlicht wird. Da ich aber sehr wahrscheinlich kein Plugin dafür schreiben muss, kann ich nicht viel zu der Schnittstelle sagen. Vielleicht später irgendwann einmal...


    Lars.

  • Wer das nicht sehen will, muss erstmal erwachsen werden.


    Genau diese Arroganz ist es, aufgrund deren ich dich nicht ernst nehmen kann.


    Ich halte mich an Styleguides wenn ich an "fremdem" Code arbeite. In meinem EIGENEN Code (und dazu zähle ich auch Plugins) mache ich das, was ICH für das am besten les- und wartbare halte. Und das ist sicher nicht der Stil des VDR-Codes.


    Tschüs.

    Asrock A75 Pro4-M
    Debian wheezy (testing, stock) (aktuell 2012-08-24: Linux 3.2, VDR 1.7.28)
    vdr-sxfe (xineliboutput)
    Pioneer VSX-520-K

  • Genau diese Arroganz ist es, aufgrund deren ich dich nicht ernst nehmen kann.


    Full Ack! Was Geronimo da ablässt...Bullshit!

  • Du willst also das andere Plugins/Module für das DLNA Plugin schreiben.
    Ich gehe mal davon aus dein Aufnahmen und LiveTV sind auch nur Module.
    Ich nenne mal die Plugins vom Plugin Module.
    Dein Headerfile enthält mir aber zuviel.


    Meine erste Frage ist scanned das Hauptprogramm selber oder soll jedes
    Modul selber scannen oder beides?


    Die Aufgaben des Modules wären:

    • Modulverwaltung (Init,Cleanup,Wakeup)
    • Erzeugen der Recourcen incl. Metadaten
    • Benachrichtigung bei Änderung einer Recource
    • Bereitstellen des Inhalts einer Resource


    Johns

    Sag mir, wo die Developer sind. Wo sind sie geblieben? . . . . . . . . . . . . . . . . . . . . SoftHdDevice - A software and GPU emulated HD output device plugin.
    Sag mir, wo die Developer sind. Was ist geschehn?


    Client0: Crown CW02 MSI_C847MS-E33 Zotac_GT640_passiv Cine-S2 iMon-MCE / streamdev softhddevice
    Client1: Lian_Li_PC-Q09FB ASRock_H67M-ITX/HT I3-2100 ASUS_ENGT520_passiv / streamdev softhddevice
    Test: Lian_Li_PC-Q09R Asus C60M1-I / streamdev
    Server0: Dockstar TT-S2-3600-USB / streamdev
    Server2: Lian_Li_PC-Q07R Intel_DH61DL G620 WD20EARX 90W PicoPSU Cine-S2+DuoFlex-S2+DuoFlex-CT / streamdev / 22 Watt Verbrauch

  • Quote

    Wenn Du mal Software für embedded System geschrieben hast, bei denen es auf jedes verbrauchte Byte ankommt, dann würdest Du anders reden.
    Wenn der VDR nur für fette PCs entwickelt wäre, ließe er sich nicht so einfach auf kleine System portieren.
    Aber dazu müsste man schon bereit sein, übern Tellerrand hinaus zu schauen, bzw. sich mit der Arbeit anderer auseinander zu setzen.


    Mir stößt es auf, wenn Möchtegern-Experten von Optimierung reden, aber nichtmal einen Benchmark geschrieben haben.
    z.B. was kostet der Einsatz von PropertyMaps an Speicher und Laufzeit und wo liegt ein möglicher Gewinn.
    Ein kleines Testproggy kann das schnell beantworten.


    Dann mach es!!! Ich habe einfach nicht die Zeit und Lust dazu mich damit zu beschäftigen und brauche die Unterstützung anderer. Ich werde auch ganz sicher nicht für ARM oder andere Linux-Derivate entwickeln, die ich selbst nicht einsetze! Du kannst aber gerne Patches beisteuern, sobald der Code verfügbar ist.


    Zur Frage:
    Die Module scannen selber und müssen selbst die Aktualisierung der Ordner an den Plugin-Manager melden. Der Plugin-Manager scannt aber die überwachten Verzeichnisse bei jedem Start des Plugins neu, da es ja vorkommen kann, dass auch außerhalb der Betriebszeit des VDRs Änderungen an der Datenbasis vorgenommen werden. Zum Beispiel, wenn es ein externes System (NAS) ist.


    Die Aufgaben sind genau richtig identifiziert, wobei "Erzeugen der Resourcen" irgendwie komisch klingt. "Ermitteln/Bereitstellen der Resourcen" passt eher.


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin