Ticket #1753: mythmediamonitor-darwin.2.cpp

File mythmediamonitor-darwin.2.cpp, 6.0 KB (added by awk@…, 13 years ago)

mythmediamonitor-darwin.cpp V2 - 'cleanup' removes some Mac OS X header dependancies

Line 
1#include "mythmediamonitor.h"
2#include "mythmediamonitor-darwin.h"
3#include "mythcdrom.h"
4#include "mythmedia.h"
5
6#include <mythtv/mythcontext.h>
7
8#include <IOKit/IOKitLib.h>
9#include <IOKit/storage/IOMedia.h>
10#include <IOKit/storage/IOCDMedia.h>
11#include <IOKit/storage/IODVDMedia.h>
12
13static mach_port_t            sMasterPort;
14
15MediaType FindDVDOrCDMedia(io_service_t service)
16{
17    kern_return_t    kernResult;
18    io_iterator_t    iter;
19    MediaType mediaType = MEDIATYPE_UNKNOWN;
20    bool isWholeMedia = false;
21   
22    // Create an iterator across all parents of the service object passed in.
23    kernResult = IORegistryEntryCreateIterator(service,
24                                               kIOServicePlane,
25                                               kIORegistryIterateRecursively | kIORegistryIterateParents,
26                                               &iter);
27   
28    if (KERN_SUCCESS != kernResult)
29    {
30        VERBOSE(VB_IMPORTANT, QString("FindDVDMedia - IORegistryEntryCreateIterator returned %1").arg(kernResult));
31    }
32    else if (!iter)
33    {
34        VERBOSE(VB_IMPORTANT, "FindDVDMedia - IORegistryEntryCreateIterator returned a NULL iterator");
35    }
36    else
37    {
38        // A reference on the initial service object is released in the do-while loop below,
39        // so add a reference to balance
40        IOObjectRetain(service);   
41       
42        do
43        {
44            isWholeMedia = false;
45            if (IOObjectConformsTo(service, kIOMediaClass))
46            {
47               
48                CFTypeRef wholeMedia;
49               
50                wholeMedia = IORegistryEntryCreateCFProperty(service,
51                                                             CFSTR(kIOMediaWholeKey),
52                                                             kCFAllocatorDefault,
53                                                             0);
54                                                           
55                if (NULL == wholeMedia)
56                {
57                    VERBOSE(VB_IMPORTANT, "IsDVDMedia - Could not retrieve Whole property");
58                }
59                else
60                {                                       
61                    isWholeMedia = CFBooleanGetValue((CFBooleanRef)wholeMedia);
62                    CFRelease(wholeMedia);
63                }
64            }
65       
66            if (isWholeMedia && (IOObjectConformsTo(service, kIODVDMediaClass)))
67            {
68                mediaType = MEDIATYPE_DVD;
69            }
70            else if (isWholeMedia && (IOObjectConformsTo(service, kIOCDMediaClass)))
71            {
72                mediaType = MEDIATYPE_AUDIO;
73            }
74            IOObjectRelease(service);
75        } while ((service = IOIteratorNext(iter)) && (mediaType == MEDIATYPE_UNKNOWN));
76
77        IOObjectRelease(iter);
78    }
79    return mediaType;
80}
81
82MediaType MediaTypeForBSDName(const char *bsdName)
83{
84    CFMutableDictionaryRef    matchingDict;
85    kern_return_t        kernResult;
86    io_iterator_t         iter;
87    io_service_t        service;
88    MediaType mediaType = MEDIATYPE_UNKNOWN;
89   
90    matchingDict = IOBSDNameMatching(sMasterPort, 0, bsdName);
91    if (NULL == matchingDict)
92    {
93        VERBOSE(VB_IMPORTANT, QString("IsDVDMediaForName(%1) - IOBSDNameMatching returned a NULL dictionary.").arg(bsdName));
94    }
95    else
96    {
97        // Return an iterator across all objects with the matching BSD node name. Note that there
98        // should only be one match!
99        kernResult = IOServiceGetMatchingServices(sMasterPort, matchingDict, &iter);   
100   
101        if (KERN_SUCCESS != kernResult)
102        {
103            VERBOSE(VB_IMPORTANT, QString("IIsDVDMediaForName - IOServiceGetMatchingServices returned %1").arg(kernResult));
104        }
105        else if (!iter)
106        {
107            VERBOSE(VB_IMPORTANT, "IIsDVDMediaForName - IOServiceGetMatchingServices returned a NULL iterator");
108        }
109        else
110        {
111            service = IOIteratorNext(iter);
112           
113            // Release this now because we only expect the iterator to contain
114            // a single io_service_t.
115            IOObjectRelease(iter);
116           
117            if (!service)
118            {
119                VERBOSE(VB_IMPORTANT, "IIsDVDMediaForName - IOIteratorNext returned a NULL iterator");
120            }
121            else
122            {
123                mediaType = FindDVDOrCDMedia(service);
124                IOObjectRelease(service);
125            }
126        }
127    }
128    return mediaType;
129}
130
131
132void diskAppearedCallback(DADiskRef disk, void *context)
133{
134    // Find out if the new disk is a DVD (or CD)
135    MediaType mediaType = MediaTypeForBSDName(DADiskGetBSDName(disk));
136    if (context && ((mediaType == MEDIATYPE_DVD) || (mediaType == MEDIATYPE_AUDIO)))
137    {
138        // Add new device
139        MonitorThread *theMonitorThread = reinterpret_cast<MonitorThread*>(context);
140        theMonitorThread->diskAppeared(DADiskGetBSDName(disk));
141    }
142}
143
144void diskDisappearedCallback(DADiskRef disk, void *context)
145{
146    if (context)
147        reinterpret_cast<MonitorThread *>(context)->diskDisappeared(DADiskGetBSDName(disk));
148}
149
150void MonitorThread::diskAppeared(QString devName)
151{
152        MythMediaDevice *media = MythCDROM::get(m_Monitor, devName, true, m_Monitor->m_AllowEject);
153        m_Monitor->AddDevice(media);
154}
155
156void MonitorThread::diskDisappeared(QString devName)
157{
158        m_Monitor->RemoveDevice(devName);
159}
160
161void MonitorThread::registerDiskArbitrationCallbacks()
162{
163    m_DiskArbitrationSession = (void *) DASessionCreate(kCFAllocatorDefault);
164    DARegisterDiskAppearedCallback( (DASessionRef) m_DiskArbitrationSession, kDADiskDescriptionMatchVolumeMountable, diskAppearedCallback, this);
165    DARegisterDiskDisappearedCallback( (DASessionRef) m_DiskArbitrationSession, kDADiskDescriptionMatchVolumeMountable, diskDisappearedCallback, this);
166
167    DASessionScheduleWithRunLoop((DASessionRef) m_DiskArbitrationSession, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
168}
169
170void MonitorThread::unregisterDiskArbitrationCallbacks()
171{
172    CFRelease((DASessionRef) m_DiskArbitrationSession);
173}