Author Topic: people who have made a media plugin, ANSWER!  (Read 13124 times)

tschak909

  • LinuxMCE God
  • ****
  • Posts: 5549
  • DOES work for LinuxMCE.
    • View Profile
people who have made a media plugin, ANSWER!
« on: December 16, 2007, 09:50:36 pm »
Okay,

I am at the end of my @#)$#@$)#@ rope.

I've even gone as far as trying to track down the guy who wrote the Xine Player/Plugin for Pluto.....message delivery failure...typical pluto

I AM PISSED!

CAN ANYONE HELP ME WITH A FEW VERY FUNDAMENTAL YET NOT INTUITIVE ASPECTS OF THE MEDIA PLUGIN?!?!?!

I'm to the point where i'm ready to start throwing chairs.

-Thom
« Last Edit: December 16, 2007, 09:54:55 pm by tschak909 »

ddamron

  • Alumni
  • wants to work for LinuxMCE
  • *
  • Posts: 962
    • View Profile
    • My LinuxMCE User Page
Re: people who have made a media plugin, ANSWER!
« Reply #1 on: December 17, 2007, 02:38:40 am »
Sorry Thom, I'm in the same boat...

I'm still trying to figure out 'simple' things for my Insteon driver....like returning state information...
FWIW, I just decided to plow on..EVENTUALLY, it'll click and I'll see what I'm doing wrong/not doing..
Glad I did, the PLM is ready for beta testing now..
The only intuitive interface is the nipple.  After that it's all learned.
My other computer is your windows box.
I'm out of my mind.  Back in 5 minutes.
Q:  What's Red and smells like blue paint?

A:  Red Paint.

tschak909

  • LinuxMCE God
  • ****
  • Posts: 5549
  • DOES work for LinuxMCE.
    • View Profile
Re: people who have made a media plugin, ANSWER!
« Reply #2 on: December 17, 2007, 07:34:30 am »
Man, I just keep getting angrier and angrier....

I see stupid shit like this IN THE #@($@#$(#@ BASE MEDIA CLASS!!!!:

MediaStream.cpp

Code: [Select]

bool MediaStream::ContainsVideo()
{
        return m_iPK_MediaType==MEDIATYPE_pluto_LiveTV_CONST ||
                m_iPK_MediaType==MEDIATYPE_pluto_DVD_CONST ||
                m_iPK_MediaType==MEDIATYPE_pluto_StoredVideo_CONST ||
                m_iPK_MediaType==MEDIATYPE_pluto_Pictures_CONST ||
                m_iPK_MediaType==MEDIATYPE_np_LiveTV_CONST ||
                m_iPK_MediaType==MEDIATYPE_np_DVD_CONST ||
                m_iPK_MediaType==MEDIATYPE_np_VideoTape_CONST ||
                m_iPK_MediaType==MEDIATYPE_np_LaserDisc_CONST ||
                m_iPK_MediaType==MEDIATYPE_np_Game_CONST;
}


stupid things like dealing with descriptions IN the base media classes referencing child media plugins!

Code: [Select]

void MediaStream::UpdateDescriptions(bool bAllFiles,MediaFile *pMediaFile_In)
{
        if( m_bPlugInWillSetDescription )
                return;

        m_sMediaDescription=""; m_sSectionDescription="";
        Media_Plugin *pMedia_Plugin = m_pMediaHandlerInfo->m_pMediaHandlerBase->m_pMedia_Plugin;

        if( m_iPK_MediaType==MEDIATYPE_pluto_StoredAudio_CONST || m_iPK_MediaType==MEDIATYPE_pluto_CD_CONST || (m_iPK_MediaT
ype==MEDIATYPE_pluto_StoredVideo_CONST && !m_bContainsTitlesOrSections) )
        {
                MediaFile *pMediaFile=pMediaFile_In;
                if( bAllFiles )
                {
                        for(size_t s=0;s<m_dequeMediaFile.size();++s)
                                UpdateDescriptions(false,m_dequeMediaFile[s]);
                        return;
                }
                else if( !pMediaFile )
                        pMediaFile = GetCurrentMediaFile();

                Row_Attribute *pRow_Attribute_Album=NULL,*pRow_Attribute_Performer=NULL,*pRow_Attribute_Title=NULL;

                // First try to find attributes for the particular song, otherwise look in the collection
                if( pMediaFile )
                {
                        if( !pRow_Attribute_Performer )
                        {
                                list_int *listPK_Attribute = pMediaFile->m_mapPK_Attribute_Find(ATTRIBUTETYPE_Performer_CONS
T);
                                if( listPK_Attribute && listPK_Attribute->size() )
                                        pRow_Attribute_Performer = pMedia_Plugin->m_pDatabase_pluto_media->Attribute_get()->
GetRow(*(listPK_Attribute->begin()));
                        }
                        if( !pRow_Attribute_Album )
                        {
                                list_int *listPK_Attribute = pMediaFile->m_mapPK_Attribute_Find(ATTRIBUTETYPE_Album_CONST);
                                if( listPK_Attribute && listPK_Attribute->size() )
                                        pRow_Attribute_Album = pMedia_Plugin->m_pDatabase_pluto_media->Attribute_get()->GetR
ow(*(listPK_Attribute->begin()));
                        }
                        if( !pRow_Attribute_Title )
                        {
                                list_int *listPK_Attribute = pMediaFile->m_mapPK_Attribute_Find(ATTRIBUTETYPE_Title_CONST);
                                if( listPK_Attribute && listPK_Attribute->size() )
                                        pRow_Attribute_Title = pMedia_Plugin->m_pDatabase_pluto_media->Attribute_get()->GetR
ow(*(listPK_Attribute->begin()));
                        }
                }

                if( !pRow_Attribute_Performer )
                {
                        list_int *listPK_Attribute = m_mapPK_Attribute_Find(ATTRIBUTETYPE_Performer_CONST);
                        if( listPK_Attribute && listPK_Attribute->size() )
                                pRow_Attribute_Performer = pMedia_Plugin->m_pDatabase_pluto_media->Attribute_get()->GetRow(*
(listPK_Attribute->begin()));
                }
                if( !pRow_Attribute_Album )
                {
                        list_int *listPK_Attribute = m_mapPK_Attribute_Find(ATTRIBUTETYPE_Album_CONST);
                        if( listPK_Attribute && listPK_Attribute->size() )
                                pRow_Attribute_Album = pMedia_Plugin->m_pDatabase_pluto_media->Attribute_get()->GetRow(*(lis
tPK_Attribute->begin()));
                }
                if( !pRow_Attribute_Title )
                {
                        list_int *listPK_Attribute = m_mapPK_Attribute_Find(ATTRIBUTETYPE_Title_CONST);
                        if( listPK_Attribute && listPK_Attribute->size() )
                                pRow_Attribute_Title = pMedia_Plugin->m_pDatabase_pluto_media->Attribute_get()->GetRow(*(lis
tPK_Attribute->begin()));
                }

                if( (pRow_Attribute_Performer || pRow_Attribute_Album) && m_iPK_MediaType!=MEDIATYPE_pluto_StoredVideo_CONST
 )
                {
                        if( pRow_Attribute_Performer )
                        {
                                m_sMediaDescription = pRow_Attribute_Performer->Name_get();
                                if( pRow_Attribute_Album )
                                        m_sMediaDescription += "\n" + pRow_Attribute_Album->Name_get();
                        }
                        else
                                m_sMediaDescription = pRow_Attribute_Album->Name_get();

                        if( pRow_Attribute_Title )
                                m_sSectionDescription = pRow_Attribute_Title->Name_get();
                        else
                                m_sSectionDescription = pMediaFile->m_sFilename;

                        if( pMediaFile )
                                pMediaFile->m_sDescription = m_sSectionDescription;
                }
                else if( pRow_Attribute_Title )
                                m_sMediaDescription = pRow_Attribute_Title->Name_get();
                else if( pMediaFile && pMediaFile->m_sFilename.size()>6 && pMediaFile->m_sFilename.substr(0,6)=="cdda:/" )
                        m_sMediaDescription = pMediaFile->m_sFilename.substr(6);
                else if( pMediaFile )
                        m_sMediaDescription = pMediaFile->m_sFilename;

                if( pMediaFile && pMediaFile->m_sDescription.size()==0 )
                        pMediaFile->m_sDescription = pMediaFile->m_sFilename;

                if( m_sMediaDescription.size()==0 )
                {
                        if( m_iPK_MediaType==MEDIATYPE_pluto_CD_CONST || !pMediaFile || pMediaFile->m_sFilename.size()==0 )
                                m_sMediaDescription = "<%=T" + StringUtils::itos(TEXT_Unknown_Disc_CONST) + "%>";
                        else
                                m_sMediaDescription = pMediaFile->m_sFilename;
                }
        }
        else if( m_iPK_MediaType==MEDIATYPE_pluto_DVD_CONST )
        {
                MediaTitle *pMediaTitle=NULL;
                MediaSection *pMediaSection=NULL;
                if( m_iDequeMediaTitle_Pos>=0 && m_iDequeMediaTitle_Pos<m_dequeMediaTitle.size() )
                        pMediaTitle = m_dequeMediaTitle[m_iDequeMediaTitle_Pos];
                if( pMediaTitle && m_iDequeMediaSection_Pos>=0 && m_iDequeMediaSection_Pos<pMediaTitle->m_dequeMediaSection.
size() )
                        pMediaSection=pMediaTitle->m_dequeMediaSection[m_iDequeMediaSection_Pos];
                else if( m_iDequeMediaSection_Pos>=0 && m_iDequeMediaSection_Pos<m_dequeMediaSection.size() )
                        pMediaSection=m_dequeMediaSection[m_iDequeMediaSection_Pos];

                Row_Attribute *pRow_Attribute_Title=NULL,*pRow_Attribute_Chapter=NULL;

                if( !pRow_Attribute_Title && pMediaTitle )
                {
                        list_int *listPK_Attribute = pMediaTitle->m_mapPK_Attribute_Find(ATTRIBUTETYPE_Title_CONST);
                        if( listPK_Attribute && listPK_Attribute->size() )
                                pRow_Attribute_Title = pMedia_Plugin->m_pDatabase_pluto_media->Attribute_get()->GetRow(*(lis
tPK_Attribute->begin()));
                }
                if( !pRow_Attribute_Title )
                {
                       list_int *listPK_Attribute = m_mapPK_Attribute_Find(ATTRIBUTETYPE_Title_CONST);
                        if( listPK_Attribute && listPK_Attribute->size() )
                                pRow_Attribute_Title = pMedia_Plugin->m_pDatabase_pluto_media->Attribute_get()->GetRow(*(lis
tPK_Attribute->begin()));
                }
                if( !pRow_Attribute_Chapter )
                {
                        list_int *listPK_Attribute = m_mapPK_Attribute_Find(ATTRIBUTETYPE_Chapter_CONST);
                        if( listPK_Attribute && listPK_Attribute->size() )
                                pRow_Attribute_Chapter = pMedia_Plugin->m_pDatabase_pluto_media->Attribute_get()->GetRow(*(l
istPK_Attribute->begin()));
                }

                if( pRow_Attribute_Title )
                        m_sMediaDescription = pRow_Attribute_Title->Name_get();
                if( pRow_Attribute_Chapter )
                        m_sSectionDescription = pRow_Attribute_Chapter->Name_get();
                else if( m_iDequeMediaTitle_Pos!=-1 && m_iDequeMediaSection_Pos!=-1 )
                        m_sSectionDescription =  "Chapter: " + StringUtils::itos(m_iDequeMediaSection_Pos+1) +
                                "\nTitle: " + StringUtils::itos(m_iDequeMediaTitle_Pos+1);
                else
                        m_sSectionDescription = "";

                if( m_sMediaDescription.size()==0 )
                {
                        MediaFile *pMediaFile=NULL;
                        if( !pMediaFile )
                                pMediaFile = GetCurrentMediaFile();

                        if( pMediaFile && !StringUtils::StartsWith(pMediaFile->m_sFilename,"/dev/") )
                                m_sMediaDescription = pMediaFile->m_sFilename;
                        else
                                m_sMediaDescription = "<%=T" + StringUtils::itos(TEXT_Unknown_Disc_CONST) + "%>";
                }
        }
        if( m_sMediaDescription.size()==0 )
        {
                MediaFile *pMediaFile = GetCurrentMediaFile();

                if( pMediaFile )
                        m_sMediaDescription = pMediaFile->m_sFilename;
                else
                {
                        DeviceData_Router *pDeviceData_Router = m_pMediaDevice_Source->m_pDeviceData_Router;
                        if( pDeviceData_Router->m_pDevice_RouteTo )  // this may be an embedded device, if so show the paren
t's description
                                pDeviceData_Router = pDeviceData_Router->m_pDevice_RouteTo;

                        Row_MediaType *pRow_MediaType = m_pMediaHandlerInfo->m_pMediaHandlerBase->m_pMedia_Plugin->m_pDataba
se_pluto_main->MediaType_get()->GetRow(m_iPK_MediaType);
                         m_sMediaDescription = pDeviceData_Router->m_sDescription;
                        if( pRow_MediaType )
                                m_sMediaDescription += "(" + pRow_MediaType->Description_get() + ")";
                }
        }
}

Stupid shit like this is making me realise that it will not be possible to make my own plugins that can optionally be installed, without telling the base Media Plug-in classes about it first....

What is this shit?

Do none of you know how to program?

This is _NOT_ how you do object oriented code, oh I forgot, this is C++, it has no effective grounding in reality.

If you as a programmer are putting references to specific inherited classes in your parent classes, this is BAD design, and should be rewritten!

I never even thought to look in here, because I never thought someone would be _STUPID_ enough to do something like this!

Funny enough, the programmer who wrote this piece of code, is no longer available at Pluto, His email address bounces.

I am continuing my analysis, but if this continues, I will have no choice but to abort this plugin, due to insanely bad design.

I am very disappointed.

-Thom


aaron.b

  • Regular Poster
  • **
  • Posts: 35
    • View Profile
Re: people who have made a media plugin, ANSWER!
« Reply #3 on: December 17, 2007, 08:08:48 am »
Thom,

I know the media plugin well and wrote a lot of it.  I don't see where a base class was ever calling a derived class.  I looked through the code snippets you copied and didn't see them there.

I understand your frustration about why the base class for MediaStream has a hardcoded list of the types of media that contain video, which is needed so the media plugin knows if it should turn on the tv or only the receiver.  This code snippet was my doing.  The logic behind it is that the types of media streams (ie video, audio, pictures, live tv, etc.) don't ever change.  And whether the plugin is for xine or mplayer or gstreamer or something else, if the media type is 'MEDIATYPE_pluto_StoredVideo' it contains video, and if it's 'MEDIATYPE_pluto_storedAudio' audio it does not.  I could have made it a pure virtual function that each derived stream had to overwrite, but since it seemed the in virtually every conceivable application the list of media types was always the same, and the list of what types of media have video content and what types do not is the same, it seemed to make the most sense to put this 'default' functionality in the base class rather than forcing each developer of each and every plugin to write the exact same duplicate code in each of the derived media streams.  This approach seemed more fool proof.  If the derived media streams (Xine, MPlayer, VLC, MythTV, VDR, Generic) each had to duplicate the same code over and over, then it would introduce (a) a lot of possibility for error in that if for any derived class the user forgot to put the same list in the same way it would make his plugin work differently than the rest, and (b) if at some point down the road there is a new type of media stream we haven't conceived you'd have to make the change in a bunch of different places rather than making it in one.

I don't really see the design flaw here, or how this conflicts with the principles of OOP.  After all, the whole premise behind OO code is re-usability and reducing duplicate code.  So, since 99% of the time the derived MediaStream will need the exact same code, it seems like the correct OO way is to put this default code in the base class, and then if for some reason a particular derived media stream wants to handle it differently, then it can always override the ContainsVideo function.  Having the default behavior in the base class doesn't mean you CAN'T change in your derived class, it just means you don't have to since, to date, nobody has ever wanted to.

And the same thing is true for UpdateDescriptions.  99% of the time the way we display descriptions is the same.  Whether you're using Xine, MPlayer, or VLC (all have plugins), when music is playing the description is Artist / Album / Song Title.  So, again, it seems logical to me to put this default behavior in the base class so you're not required to duplicate the same code over and over and over again in each of the derived classes.  It also introduces uniformity.  If we took it out of the base class and put it in each of the derived classes as you suggest, then it's up to each programmer (and xine, mplayer and vlc plugins were all done by different programmers) to implement the description display the same way.  That means when listening to a song through Xine, it may appear as Artist / Album / Song, but when you move to another room where it's played through MPLayer, it's displayed as Song / Album Artist.  Again, having the default behavior in the base class doesn't mean you CAN'T change the way descriptions are handled in MPlayer, it just means you don't have to, and if you leave it alone, there will be a consistent, uniform way of presenting descriptions across all plugins.

How is this creating a problem for you?  If you want to override the default 'ContainsVideo' and 'UpdateDescriptions' for your particular media plugin, how does having the default versions in the base class hurt you?  And where do you see a base class ever call a pointer to a derived class?  Can you show me what line you saw that in?  I agree if that happened it would be bad, but I just don't see where it ever did.

You can email me to aaron.b  [at] plutohome [dot] com


tschak909

  • LinuxMCE God
  • ****
  • Posts: 5549
  • DOES work for LinuxMCE.
    • View Profile
Re: people who have made a media plugin, ANSWER!
« Reply #4 on: December 17, 2007, 08:34:19 am »
wow, aaron.b actually answers.

How am I supposed to add other media types as optional packages if I am probably going to have to modify the base Media stuff?

I've been looking at all this code for three weeks straight, and getting more angry every time I look at it, because it's relatively undocumented, and I'm no closer to getting the system to even recognise that I have added a new plugin/player type to handle my new media type!

what's the point of all the OO, when there is hard-coded crap all over the place?

-Thom

Matthew

  • Douchebag
  • Addicted
  • *
  • Posts: 567
    • View Profile
Re: people who have made a media plugin, ANSWER!
« Reply #5 on: December 17, 2007, 08:59:52 am »
I don't see where a base class was ever calling a derived class.
(...)
I understand your frustration about why the base class for MediaStream has a hardcoded list of the types of media that contain video, which is needed so the media plugin knows if it should turn on the tv or only the receiver.  This code snippet was my doing.  The logic behind it is that the types of media streams (ie video, audio, pictures, live tv, etc.) don't ever change.  And whether the plugin is for xine or mplayer or gstreamer or something else, if the media type is 'MEDIATYPE_pluto_StoredVideo' it contains video, and if it's 'MEDIATYPE_pluto_storedAudio' audio it does not.  I could have made it a pure virtual function that each derived stream had to overwrite, but since it seemed the in virtually every conceivable application the list of media types was always the same, and the list of what types of media have video content and what types do not is the same, it seemed to make the most sense to put this 'default' functionality in the base class rather than forcing each developer of each and every plugin to write the exact same duplicate code in each of the derived media streams.  This approach seemed more fool proof.  If the derived media streams (Xine, MPlayer, VLC, MythTV, VDR, Generic) each had to duplicate the same code over and over, then it would introduce (a) a lot of possibility for error in that if for any derived class the user forgot to put the same list in the same way it would make his plugin work differently than the rest, and (b) if at some point down the road there is a new type of media stream we haven't conceived you'd have to make the change in a bunch of different places rather than making it in one.

I don't really see the design flaw here, or how this conflicts with the principles of OOP.  After all, the whole premise behind OO code is re-usability and reducing duplicate code.  So, since 99% of the time the derived MediaStream will need the exact same code, it seems like the correct OO way is to put this default code in the base class, and then if for some reason a particular derived media stream wants to handle it differently, then it can always override the ContainsVideo function.  Having the default behavior in the base class doesn't mean you CAN'T change in your derived class, it just means you don't have to since, to date, nobody has ever wanted to.

And the same thing is true for UpdateDescriptions.  99% of the time the way we display descriptions is the same.  Whether you're using Xine, MPlayer, or VLC (all have plugins), when music is playing the description is Artist / Album / Song Title.  So, again, it seems logical to me to put this default behavior in the base class so you're not required to duplicate the same code over and over and over again in each of the derived classes.  It also introduces uniformity.  If we took it out of the base class and put it in each of the derived classes as you suggest, then it's up to each programmer (and xine, mplayer and vlc plugins were all done by different programmers) to implement the description display the same way.  That means when listening to a song through Xine, it may appear as Artist / Album / Song, but when you move to another room where it's played through MPLayer, it's displayed as Song / Album Artist.  Again, having the default behavior in the base class doesn't mean you CAN'T change the way descriptions are handled in MPlayer, it just means you don't have to, and if you leave it alone, there will be a consistent, uniform way of presenting descriptions across all plugins.

How is this creating a problem for you?  If you want to override the default 'ContainsVideo' and 'UpdateDescriptions' for your particular media plugin, how does having the default versions in the base class hurt you?  And where do you see a base class ever call a pointer to a derived class?  Can you show me what line you saw that in?  I agree if that happened it would be bad, but I just don't see where it ever did.

That method doesn't have pointers to subclasses in it (which is OK, containing a subclass as a member is confusing, but still correct OOP), but it does have references to a hardcoded list of types of subclasses. That's not OOP. In order to add a new subclass which contains video, the MediaStream class has to be subclassed and MediaStream::ContainsVideo() overridden with another test that reiterates all those other sister classes' responses. Different daughter classes shouldn't have that kind of info about other daughter classes.

The correct way to do it is to make MediaStream::ContainsVideo() return whether a MediaStream object (not any subclasses) contains video or not. Which in turn should be overridden by the subclass' own method that returns whether the subclass itself contains video or not. That is proper encapsulation.

From the rant I inferred that MediaStream::ContainsVideo() was just an example of poor understanding of OOP and the consequences of that crude design. Your response tends to confirm that inference.

darrenmason

  • Addicted
  • *
  • Posts: 529
    • View Profile
Re: people who have made a media plugin, ANSWER!
« Reply #6 on: December 17, 2007, 01:01:09 pm »


The logic behind it is that the types of media streams (ie video, audio, pictures, live tv, etc.) don't ever change. 

I don't really see the design flaw here, or how this conflicts with the principles of OOP.  After all, the whole premise behind OO code is re-usability and reducing duplicate code.  So, since 99% of the time the derived MediaStream will need the exact same code, it seems like the correct OO way is to put this default code in the base class, and then if for some reason a particular derived media stream wants to handle it differently, then it can always override the ContainsVideo function.  Having the default behavior in the base class doesn't mean you CAN'T change in your derived class, it just means you don't have to since, to date, nobody has ever wanted to.

And the same thing is true for UpdateDescriptions.  99% of the time the way we display descriptions is the same.  Whether you're using Xine, MPlayer, or VLC (all have plugins), when music is playing the description is Artist / Album / Song Title.  So, again, it seems logical to me to put this default behavior in the base class so you're not required to duplicate the same code over and over and over again in each of the derived classes.  It also introduces uniformity.  If we took it out of the base class and put it in each of the derived classes as you suggest, then it's up to each programmer (and xine, mplayer and vlc plugins were all done by different programmers) to implement the description display the same way.  That means when listening to a song through Xine, it may appear as Artist / Album / Song, but when you move to another room where it's played through MPLayer, it's displayed as Song / Album Artist.  Again, having the default behavior in the base class doesn't mean you CAN'T change the way descriptions are handled in MPlayer, it just means you don't have to, and if you leave it alone, there will be a consistent, uniform way of presenting descriptions across all plugins.


This response has left me rather dejected, firstly due to seeing the code and the problems that Matthew has already pointed out and secondly from the logic in the response.

To state types of media streams will 'never' change has been proven wrong by this thread and what Thom is trying to achieve (which should fit nicely withing the basic design of the system btw)
If the media stream type determines if it containsVideo or not then that is where the logic should be encapsualted - in each media stream class. If you add a new one then it will need to decide if it contains video or not. The base class should not have explicit knowledge of its children.

Whereever there is logic like this;
if (some type)
 ... do something
else if (some other type)
 ... do something else
else if (yet another type)
 ... do something else
else ...

Then is is obviously not generalised code and should be encapsulated in each of the classes.

The pluto code seems to do this an awful lot. Base media streams knowing about all the stream types (or at least some). Base plugins/players knowing about its children.
What is just as frustrating is other objects with unnecessary knowledge of specific devices. Like Orbiter knowing about the Xine_player.

And the whole premise behind OO code is NOT reusability and reducing duplicate code - encapsulation and resilience to change is far more important. Reusability of patterns and not having to change tested code when implementing changes is what OOP is about.

I just hope that a lot of this code is fixable.

Thom, keep at it. At least with enough like minded people with enough motivation things can get sorted out.

Darren

tschak909

  • LinuxMCE God
  • ****
  • Posts: 5549
  • DOES work for LinuxMCE.
    • View Profile
Re: people who have made a media plugin, ANSWER!
« Reply #7 on: December 17, 2007, 02:21:33 pm »
I come from the Alan Kay school of OO design, I love Smalltalk.

basically, that the best way to model a design is from nature, cells, well encapsulated, sending what they need and recieving what they need. C++ to me has always been like trying to replicate a swiss watch. The best ones look beautiful on the inside, but when you scale a swiss watch, what do you get? A CLOCK TOWER.... just bigger gears.

-Thom

Matthew

  • Douchebag
  • Addicted
  • *
  • Posts: 567
    • View Profile
Re: people who have made a media plugin, ANSWER!
« Reply #8 on: December 17, 2007, 03:25:22 pm »
I come from the Alan Kay school of OO design, I love Smalltalk.

basically, that the best way to model a design is from nature, cells, well encapsulated, sending what they need and recieving what they need. C++ to me has always been like trying to replicate a swiss watch. The best ones look beautiful on the inside, but when you scale a swiss watch, what do you get? A CLOCK TOWER.... just bigger gears.

Well, I like C++, but it always requires that the system get some time in upfront pure design before implementation. In fact, that's why I like it. That upfront design requirement doesn't just mean that the system gets some design, but also it's a barrier to entry for programmers who don't do upfront design. Or at least it should be - not in this case, as in others.

The problem you're having isn't with C++. It's with the upfront design, or the professional discipline to stick with it, by the Pluto developers. That base class shouldn't be running logic that belongs in its subclasses, about their members. Proper C++ should use the logic implicit in the subclass' type. with methods properly overridden in the subclass rather than an "all-knowing" base class.

To quote yet another wisdom in this thread: "C trusts the programmer. C++ puts a shotgun in their hands and its barrel in your mouth and trusts the programmer."

aaron.b

  • Regular Poster
  • **
  • Posts: 35
    • View Profile
Re: people who have made a media plugin, ANSWER!
« Reply #9 on: December 17, 2007, 04:58:11 pm »
>> but it does have references to a hardcoded list of types of subclasses.

I don't see where it has any hardcoded references to sub classes.  StoredVideo, StoredAudio, LiveTV, InternetRadio are not sub classes.  They are the types of media that any of the sub classes can handle.

The base class is MediaStream.  The subclasses (so far) are XineMediaStream, VDRMediaStream, MythTVMediaStream, now MPlayerMediaStream, in the future GStreamerMediaStream, and so on.

All of them share the same list of media types, and play one or more of those types.  They can all play a subset of Video, Audio, LiveTV, InternetRadio, etc.  And whether you're using Xine, MPlayer, VDR, Myth, etc., the type 'Video' and 'LiveTV' always contain video, and the type 'Audio' and 'InternetRadio' do not.  The purpose of ContainsVideo is simple.  It's just to know if the TV should be turned on or not.  I still don't see what's wrong with having this list in the base class as *a default fallback*.  If you're creating your own media plugin and in your case InternetRadio does contain video, then in your derived media stream just define ContainsVideo and put your own logic in there.

I wrote the VDR Plugin, for example.  It took me less than 1 hour to write VDR Plugin and get to the point where there's a VDR button on the menu and when you choose it, the TV comes on, goes to the right inputs, the stereo, etc., any other media in the zone is stopped, and the VDR device is started.  And it took very little code.  This is because 99% of the logic is the same between VDR, Myth, Xine, and the other media plugins.  So having default behavior, like a function 'ContainsVideo' which knows that media type LiveTV has video, saved a ton of coding and time, and reduced the chance of errors a lot.  If the base class didn't have this functionality and to add my VDR Plugin I had to write all the code all over again which, for example, determines that LiveTV has video, and to turn on the TV, and all that other stuff, it would have taken a lot longer and introduced a lot more possibilities for errors.

Note: I'm not saying the design is great, nor that VDR only took 1 hour to implement.  I'm sure the design could be improved upon, and welcome all the feedback.  It just seems the function in question is very, very trivial and insignificant.  It's a tiny piece of logic that just that returns true for Video and LiveTV since there's a video component, and for Music and Internet Radio returns false.  A lot of the code in Media Plugin does get really complex.  And there's a lot of spaghetti code that could be much improved.  This 'ContainsVideo' function represents 0.000001% of the work and logic in Media Plugin, and is just a tiny trivial function.  So I humbly suggest that while it may be possible to improve it, spending this much effort engineering an OO to a function that is so simple is really over-engineering.  I still have trouble understanding how it could possibly get in anybody's way.  Again, if you're doing your own derived Media Stream and don't like the hardcoded list, just change it in your derived class.  It can't possibly get in your way since you can change it if you like.  But since Xine, Myth, VDR, VLC, MPlayer, etc. all use the same list the same way (ie in all of them Video and LiveTV have video, and Audio and InternetRadio do not), why remove this code from change the base class, forcing us to copy/paste the same identical code into each of the derived classes?

BTW, there was already a media type for games anyway, which you'll see is in the list.  So if you just give your derived MediaStream for games that media type, the TV should come on without you needing to write any code.  But back to Thom's original post that he can't create a new plugin because he doesn't like the behavior of ContainsVideo in the base class, just override it in your derived class and then this much maligned code in the base class will never get called.

tschak909

  • LinuxMCE God
  • ****
  • Posts: 5549
  • DOES work for LinuxMCE.
    • View Profile
Re: people who have made a media plugin, ANSWER!
« Reply #10 on: December 17, 2007, 05:18:17 pm »
no, you missed the point,

I was merely pointing to those two examples, because those happened to be open in my edit window at that moment, and they were within cursor-shot.

There are a lot more.

I started looking, because no matter what I did to the database, I could never seem to get a mediatype to attempt to use my still stubbed MAME devices, just knowing they made it TO the plugins themselves, so that I could start writing the wrappers, and try to understand the interactions between the DCE router plugins and their associated players....

...because....

the documentation is less than usable, and that's being diplomatic.

In the end, I'd just like to be able to add my new code, and a lot of us would like to be able to do that too, without having to fold it all back into LinuxMCE and have to recompile everything, because the base classes contain foreknowledge of the things derived from them.

-Thom



Matthew

  • Douchebag
  • Addicted
  • *
  • Posts: 567
    • View Profile
Re: people who have made a media plugin, ANSWER!
« Reply #11 on: December 17, 2007, 05:36:19 pm »
But since Xine, Myth, VDR, VLC, MPlayer, etc. all use the same list the same way (ie in all of them Video and LiveTV have video, and Audio and InternetRadio do not), why remove this code from change the base class, forcing us to copy/paste the same identical code into each of the derived classes?

The base class shouldn't know whether subclasses contain video or not, just that they might. Even more important and obvious, no subclass should have any knowledge of whether other subclasses contain video or not. The current approach would require, when adding a subclass, also adding to that list of media types new types of video, whenever that new subclass contains a new type of video, revising the other subclasses. That is not OOP.

This bad OOP was cited as just one example. You now imply that the problem is all through the code. That means fixing this problem is going to be a lot of work. Even just finding where the bad approach was used, with hidden roadblocks strewn throughout the code paths.

tschak909

  • LinuxMCE God
  • ****
  • Posts: 5549
  • DOES work for LinuxMCE.
    • View Profile
Re: people who have made a media plugin, ANSWER!
« Reply #12 on: December 17, 2007, 05:38:15 pm »
I call for this thread to be closed. Pending a future audit of the code to try and deal with the design issues when we can.

aaron.b has offered to help, and I will try to work with him, perhaps in the hope of trying to get a documentable process for at least the media subsystem.

-Thom

totallymaxed

  • LinuxMCE God
  • ****
  • Posts: 4660
  • Smart Home Consulting
    • View Profile
    • Dianemo - at home with technology
Re: people who have made a media plugin, ANSWER!
« Reply #13 on: December 17, 2007, 06:03:45 pm »
I call for this thread to be closed. Pending a future audit of the code to try and deal with the design issues when we can.

aaron.b has offered to help, and I will try to work with him, perhaps in the hope of trying to get a documentable process for at least the media subsystem.

-Thom


Thats great Thom. Aaron.b has been involved in the Pluto world from the very beginning... and what he does not know about Pluto/LinuxMCE is not worth knowing. Aaron is a great guy and it would be fantastic if he felt like all of us here were his friends and would welcome him without here. Working with Aaron to cleanup code or implementations and get more of you guys producing great new capabilities and features after all is what counts and Aaron can be more useful to you all in that respect than anyone else I know.

Great to see you here Aaron :-)
Andy Herron,
CHT Ltd

For Dianemo/LinuxMCE consulting advice;
@herron on Twitter, totallymaxed+inquiries@gmail.com via email or PM me here.

Get Dianemo-Rpi2 ARM Licenses http://forum.linuxmce.org/index.php?topic=14026.0

Get RaspSqueeze-CEC or Raspbmc-CEC for Dianemo/LinuxMCE: http://wp.me/P4KgIc-5P

Facebook: https://www.facebook.com/pages/Dianemo-Home-Automation/226019387454465

http://www.dianemo.co.uk

Matthew

  • Douchebag
  • Addicted
  • *
  • Posts: 567
    • View Profile
Re: people who have made a media plugin, ANSWER!
« Reply #14 on: December 17, 2007, 06:10:18 pm »
I call for this thread to be closed. Pending a future audit of the code to try and deal with the design issues when we can.

aaron.b has offered to help, and I will try to work with him, perhaps in the hope of trying to get a documentable process for at least the media subsystem.

Thats great Thom. Aaron.b has been involved in the Pluto world from the very beginning... and what he does not know about Pluto/LinuxMCE is not worth knowing. Aaron is a great guy and it would be fantastic if he felt like all of us here were his friends and would welcome him without here. Working with Aaron to cleanup code or implementations and get more of you guys producing great new capabilities and features after all is what counts and Aaron can be more useful to you all in that respect than anyone else I know.

Great to see you here Aaron :-)

I just want to be clear that, though I have criticisms of the OOP I've seen reported here, I am grateful for it anyway. I am impressed by, and grateful to, Pluto's pioneering work. And its opening the source. And its ongoing help with the LMCE project. All of which means Aaron. Please don't take these criticisms of the OOP, which are posted here for a developers audience which is working with that code to improve it, as anything but constructive investigations of the work we're now all doing together. Thanks, Aaron, and thanks for volunteering so much, including discussing this subject in this thread.