66 #include <sbIDevice.h>
67 #include <sbIDeviceController.h>
68 #include <sbIDeviceControllerRegistrar.h>
69 #include <sbIDeviceEvent.h>
72 #include <nsComponentManagerUtils.h>
73 #include <nsIClassInfoImpl.h>
74 #include <nsIProgrammingLanguage.h>
75 #include <nsIWritablePropertyBag.h>
77 #include <nsServiceManagerUtils.h>
114 NS_ENSURE_ARG_POINTER(aRegistrar);
117 RegisterControllers(aRegistrar);
129 sbIPDMarshall::BeginMonitoring()
134 nsAutoMonitor mon(mMonitor);
137 rv = InitializeVolumeMonitor();
138 NS_ENSURE_SUCCESS(rv, rv);
141 rv = ScanForConnectedDevices();
142 NS_ENSURE_SUCCESS(rv, rv);
154 sbIPDMarshall::StopMonitoring()
157 nsAutoMonitor mon(mMonitor);
160 FinalizeVolumeMonitor();
175 sbIPDMarshall::GetId(nsID** aId)
178 NS_ENSURE_ARG_POINTER(aId);
181 nsID* pId =
static_cast<nsID*
>(NS_Alloc(
sizeof(nsID)));
182 NS_ENSURE_TRUE(pId, NS_ERROR_OUT_OF_MEMORY);
198 sbIPDMarshall::GetName(nsAString&
aName)
217 mVolumeEventHandler(NULL),
218 mVolumeEventHandlerRef(NULL)
225 mMonitor = nsAutoMonitor::NewMonitor(
"sbIPDMarshall.mMonitor");
226 NS_ENSURE_TRUE(mMonitor, );
229 mDeviceManager = do_GetService(
"@songbirdnest.com/Songbird/DeviceManager;2",
231 NS_ENSURE_SUCCESS(rv, );
232 mDeviceRegistrar = do_QueryInterface(mDeviceManager, &rv);
233 NS_ENSURE_SUCCESS(rv, );
247 FinalizeVolumeMonitor();
252 nsAutoMonitor::DestroyMonitor(mMonitor);
257 mDeviceManager = nsnull;
258 mDeviceRegistrar = nsnull;
273 sbIPDMarshall::InitializeVolumeMonitor()
275 EventTypeSpec volumeEventTypes[] =
276 { { kEventClassVolume, kEventVolumeMounted },
277 { kEventClassVolume, kEventVolumeUnmounted } };
278 OSStatus error = noErr;
284 mVolumeEventHandler = NewEventHandlerUPP(VolumeEventHandler);
285 NS_ENSURE_TRUE(mVolumeEventHandler, NS_ERROR_OUT_OF_MEMORY);
286 error = InstallApplicationEventHandler(mVolumeEventHandler,
287 GetEventTypeCount(volumeEventTypes),
290 &mVolumeEventHandlerRef);
291 NS_ENSURE_TRUE(error == noErr, NS_ERROR_FAILURE);
294 autoFinalizeVolumeMonitor.forget();
305 sbIPDMarshall::FinalizeVolumeMonitor()
308 if (mVolumeEventHandlerRef) {
309 RemoveEventHandler(mVolumeEventHandlerRef);
310 mVolumeEventHandlerRef = NULL;
312 if (mVolumeEventHandler) {
313 DisposeEventHandlerUPP(mVolumeEventHandler);
314 mVolumeEventHandler = NULL;
335 sbIPDMarshall::VolumeEventHandler(EventHandlerCallRef aNextHandler,
340 NS_ENSURE_TRUE(aHandlerCtx, eventNotHandledErr);
343 FIELD_LOG((
"Enter: sbIPDMarshall::VolumeEventHandler\n"));
347 psbIPDMarshall->VolumeEventHandler(aNextHandler, aEventRef);
350 FIELD_LOG((
"Exit: sbIPDMarshall::VolumeEventHandler\n"));
353 return eventNotHandledErr;
357 sbIPDMarshall::VolumeEventHandler(EventHandlerCallRef aNextHandler,
360 OSStatus error = noErr;
363 FSVolumeRefNum volumeRefNum = kFSInvalidVolumeRefNum;
364 error = GetEventParameter(aEventRef,
365 kEventParamDirectObject,
368 sizeof(volumeRefNum),
371 NS_ENSURE_TRUE(error == noErr, );
374 UInt32 eventType = GetEventKind(aEventRef);
379 case kEventVolumeMounted :
381 if (IsIPod(volumeRefNum))
382 HandleAddedEvent(volumeRefNum);
385 case kEventVolumeUnmounted :
386 HandleRemovedEvent(volumeRefNum);
403 sbIPDMarshall::HandleAddedEvent(FSVolumeRefNum aVolumeRefNum)
405 nsCOMPtr<sbIDevice> device;
409 nsAutoMonitor mon(mMonitor);
412 FIELD_LOG((
"Enter: HandleAddedEvent %d\n", aVolumeRefNum));
415 if (mDeviceList.Get(aVolumeRefNum, getter_AddRefs(device)))
419 nsCOMPtr<nsIWritablePropertyBag>
420 propBag = do_CreateInstance(
"@mozilla.org/hash-property-bag;1", &rv);
421 NS_ENSURE_SUCCESS(rv, );
422 rv = propBag->SetProperty(NS_LITERAL_STRING(
"DeviceType"),
424 NS_ENSURE_SUCCESS(rv, );
426 rv = propBag->SetProperty(NS_LITERAL_STRING(
"VolumeRefNum"),
428 NS_ENSURE_SUCCESS(rv, );
429 nsAutoString mountPoint;
430 rv = GetVolumePath(aVolumeRefNum, mountPoint);
431 NS_ENSURE_SUCCESS(rv, );
432 rv = propBag->SetProperty(NS_LITERAL_STRING(
"MountPath"),
434 NS_ENSURE_SUCCESS(rv, );
436 nsAutoString firewireGUID;
437 rv = GetFirewireGUID(aVolumeRefNum, firewireGUID);
438 NS_ENSURE_SUCCESS(rv, );
439 rv = propBag->SetProperty(NS_LITERAL_STRING(
"FirewireGUID"),
441 NS_ENSURE_SUCCESS(rv, );
449 rv = controller->CreateDevice(propBag, getter_AddRefs(device));
450 NS_ENSURE_SUCCESS(rv, );
453 rv = mDeviceRegistrar->RegisterDevice(device);
454 NS_ENSURE_SUCCESS(rv, );
457 mDeviceList.Put(aVolumeRefNum, device);
474 sbIPDMarshall::HandleRemovedEvent(FSVolumeRefNum aVolumeRefNum)
479 FIELD_LOG((
"Enter: HandleRemovedEvent %d\n", aVolumeRefNum));
482 nsCOMPtr<sbIDevice> device;
483 if (!mDeviceList.Get(aVolumeRefNum, getter_AddRefs(device)))
487 nsCOMPtr<sbIDeviceRegistrar> deviceRegistrar =
488 do_GetService(
"@songbirdnest.com/Songbird/DeviceManager;2", &rv);
489 NS_ENSURE_SUCCESS(rv, );
490 nsCOMPtr<sbIDeviceControllerRegistrar> deviceControllerRegistrar =
491 do_GetService(
"@songbirdnest.com/Songbird/DeviceManager;2", &rv);
492 NS_ENSURE_SUCCESS(rv, );
495 nsID *controllerID = nsnull;
496 rv = device->GetControllerId(&controllerID);
500 nsCOMPtr<sbIDeviceController> deviceController;
501 if (NS_SUCCEEDED(rv)) {
502 rv = deviceControllerRegistrar->GetController
504 getter_AddRefs(deviceController));
507 NS_WARNING(
"Failed to get device controller.");
508 deviceController = nsnull;
512 if (deviceController) {
513 rv = deviceController->ReleaseDevice(device);
515 NS_WARNING(
"Failed to release device.");
519 rv = deviceRegistrar->UnregisterDevice(device);
521 NS_WARNING(
"Failed to unregister device.");
524 mDeviceList.Remove(aVolumeRefNum);
532 FIELD_LOG((
"Enter: HandleRemovedEvent\n"));
547 sbIPDMarshall::ScanForConnectedDevices()
552 FIELD_LOG((
"Enter: sbIPDMarshall::ScanForConnectedDevices\n"));
555 for (ItemCount volumeIndex = 1; ; volumeIndex++) {
557 FSVolumeInfo volumeInfo;
558 FSVolumeRefNum volumeRefNum;
559 HFSUniStr255 volumeName;
560 bzero(&volumeInfo,
sizeof(volumeInfo));
561 error = FSGetVolumeInfo(kFSInvalidVolumeRefNum,
574 FIELD_LOG((
"1: sbIPDMarshall::ScanForConnectedDevices %d\n", volumeRefNum));
577 if (IsIPod(volumeRefNum)) {
578 HandleAddedEvent(volumeRefNum);
583 FIELD_LOG((
"Exit: sbIPDMarshall::ScanForConnectedDevices\n"));
602 sbIPDMarshall::IsIPod(FSVolumeRefNum volumeRefNum)
604 GetVolParmsInfoBuffer volumeParms;
606 char *bsdDevName = NULL;
607 CFMutableDictionaryRef dictionaryRef;
608 io_service_t volNode = (io_service_t) NULL;
609 io_registry_entry_t scsiNode = (io_registry_entry_t) NULL;
610 PRBool isIPod = PR_FALSE;
611 OSStatus error = noErr;
614 LOG(
"1: IPodDevIfIsIPod\n");
617 pb.ioParam.ioNamePtr = NULL;
618 pb.ioParam.ioVRefNum = volumeRefNum;
619 pb.ioParam.ioBuffer = (Ptr) &volumeParms;
620 pb.ioParam.ioReqCount =
sizeof(volumeParms);
621 error = PBHGetVolParmsSync(&pb);
622 if (error == noErr) {
623 bsdDevName = (
char *) volumeParms.vMDeviceID;
627 LOG(
"2: IPodDevIfIsIPod %s\n", bsdDevName);
630 if (error == noErr) {
631 dictionaryRef = IOBSDNameMatching(kIOMasterPortDefault, 0, bsdDevName);
632 if (dictionaryRef == NULL) {
636 if (error == noErr) {
637 volNode = IOServiceGetMatchingService(kIOMasterPortDefault,
639 if (volNode == ((io_service_t) NULL)) {
645 LOG(
"2: IPodDevIfIsIPod %d\n", (
int) error);
648 if (error == noErr) {
649 io_registry_entry_t
node = (io_registry_entry_t) NULL;
650 io_registry_entry_t parentNode;
651 kern_return_t result = KERN_SUCCESS;
652 Boolean
done = FALSE;
658 result = IORegistryEntryGetParentEntry(node, kIOServicePlane,
660 IOObjectRelease(node);
661 node = (io_registry_entry_t) NULL;
662 if (result == KERN_SUCCESS) {
669 if (result == KERN_SUCCESS) {
670 if (IOObjectConformsTo(node,
"IOSCSIPeripheralDeviceNub")) {
672 node = (io_registry_entry_t) NULL;
679 if (node != ((io_registry_entry_t) NULL)) {
680 IOObjectRelease(node);
685 LOG(
"3: IPodDevIfIsIPod 0x%08x\n", scsiNode);
688 if ((error == noErr) && (scsiNode != ((io_registry_entry_t) NULL))) {
689 __CFString *vendorID = NULL;
690 __CFString *productID = NULL;
693 vendorID = (__CFString *) IORegistryEntryCreateCFProperty(scsiNode,
694 CFSTR(
"Vendor Identification"), kCFAllocatorDefault, 0);
695 productID = (__CFString *) IORegistryEntryCreateCFProperty(scsiNode,
696 CFSTR(
"Product Identification"), kCFAllocatorDefault, 0);
699 LOG(
"4: IPodDevIfIsIPod \"%s\" \"%s\"\n", (
char *) vendorID,
704 if (CFStringCompare(CFSTR(
"Apple"), vendorID, 0)) {
706 }
else if (CFStringCompare(CFSTR(
"iPod"), productID, 0)) {
711 if (vendorID != NULL) {
714 if (productID != NULL) {
715 CFRelease(productID);
720 LOG(
"5: IPodDevIfIsIPod %d\n", (
int) error);
723 if (scsiNode != ((io_registry_entry_t) NULL)) {
724 IOObjectRelease(scsiNode);
726 if (volNode != ((io_service_t) NULL)) {
727 IOObjectRelease(volNode);
745 sbIPDMarshall::GetVolumePath(FSVolumeRefNum aVolumeRefNum,
746 nsAString &aVolumePath)
752 error = FSGetVolumeInfo(aVolumeRefNum,
759 NS_ENSURE_TRUE(error == noErr, NS_ERROR_FAILURE);
762 cfref<CFURLRef> volumeURLRef = CFURLCreateFromFSRef(kCFAllocatorDefault,
764 NS_ENSURE_TRUE(volumeURLRef, NS_ERROR_FAILURE);
768 CFURLCopyFileSystemPath(volumeURLRef,
769 kCFURLPOSIXPathStyle);
770 NS_ENSURE_TRUE(volumePathStringRef, NS_ERROR_FAILURE);
773 CFIndex volumePathLength = CFStringGetLength(volumePathStringRef);
774 PRUnichar* volumePath = aVolumePath.BeginWriting(volumePathLength);
775 NS_ENSURE_TRUE(volumePath, NS_ERROR_OUT_OF_MEMORY);
776 CFStringGetCharacters(volumePathStringRef,
777 CFRangeMake(0, volumePathLength),
795 sbIPDMarshall::GetFirewireGUID(FSVolumeRefNum aVolumeRefNum,
796 nsAString &aFirewireGUID)
798 GetVolParmsInfoBuffer volumeParms;
800 char *bsdDevName = NULL;
801 CFMutableDictionaryRef dictionaryRef;
802 io_service_t volNode = (io_service_t) NULL;
803 io_registry_entry_t usbDevNode = (io_registry_entry_t) NULL;
804 OSStatus error = noErr;
807 pb.ioParam.ioNamePtr = NULL;
808 pb.ioParam.ioVRefNum = aVolumeRefNum;
809 pb.ioParam.ioBuffer = (Ptr) &volumeParms;
810 pb.ioParam.ioReqCount =
sizeof(volumeParms);
811 error = PBHGetVolParmsSync(&pb);
812 if (error == noErr) {
813 bsdDevName = (
char *) volumeParms.vMDeviceID;
817 if (error == noErr) {
818 dictionaryRef = IOBSDNameMatching(kIOMasterPortDefault, 0, bsdDevName);
819 if (dictionaryRef == NULL) {
823 if (error == noErr) {
824 volNode = IOServiceGetMatchingService(kIOMasterPortDefault, dictionaryRef);
825 if (volNode == ((io_service_t) NULL)) {
831 if (error == noErr) {
832 io_registry_entry_t node = (io_registry_entry_t) NULL;
833 io_registry_entry_t parentNode;
834 kern_return_t result = KERN_SUCCESS;
835 Boolean done = FALSE;
839 IOObjectRetain(volNode);
842 result = IORegistryEntryGetParentEntry(node, kIOServicePlane,
844 IOObjectRelease(node);
845 node = (io_registry_entry_t) NULL;
846 if (result == KERN_SUCCESS) {
853 if (result == KERN_SUCCESS) {
854 if (IOObjectConformsTo(node,
"IOUSBDevice")) {
856 node = (io_registry_entry_t) NULL;
863 if (node != ((io_registry_entry_t) NULL)) {
864 IOObjectRelease(node);
870 if ((error == noErr) && (usbDevNode != ((io_registry_entry_t) NULL))) {
871 __CFString *serialNumber = NULL;
872 char cSerialNumber[256];
876 serialNumber = (__CFString *) IORegistryEntryCreateCFProperty(usbDevNode,
877 CFSTR(
"USB Serial Number"), kCFAllocatorDefault, 0);
881 success = CFStringGetCString(serialNumber, cSerialNumber,
882 sizeof(cSerialNumber), kCFStringEncodingUTF8);
884 aFirewireGUID.AssignLiteral(cSerialNumber);
889 if (serialNumber != NULL) {
890 CFRelease(serialNumber);
895 if (usbDevNode != ((io_registry_entry_t) NULL)) {
896 IOObjectRelease(usbDevNode);
898 if (volNode != ((io_service_t) NULL)) {
899 IOObjectRelease(volNode);
902 return (error == noErr) ?
NS_OK : NS_ERROR_UNEXPECTED;
906 sbIPDMarshall::RemoveDevice(
sbIDevice* aDevice)
908 return NS_ERROR_NOT_IMPLEMENTED;
#define SB_PRLOG_SETUP(x)
nsresult CreateAndDispatchDeviceManagerEvent(PRUint32 aType, nsIVariant *aData, nsISupports *aOrigin, PRUint32 aDeviceState, PRBool aAsync)
Songbird iPod Device Utility Definitions.
NS_DECL_ISUPPORTS NS_DECL_SBIDEVICEMARSHALL NS_DECL_NSICLASSINFO sbIPDMarshall()
friend class sbAutoFinalizeVolumeMonitor
const unsigned long EVENT_DEVICE_ADDED
NS_IMPL_THREADSAFE_RELEASE(sbRequestItem)
NS_IMPL_THREADSAFE_ADDREF(sbRequestItem)
sbIDeviceController * FindCompatibleControllers(nsIPropertyBag *deviceParams)
#define SB_IPDMARSHALL_CLASSNAME
Songbird iPod Device Logging Definitions.
const unsigned long EVENT_DEVICE_REMOVED
[UNIMPLEMENTED UNTIL AFTER 0.3]
#define SB_IPDMARSHALL_CID
#define SB_DEVICE_CONTROLLER_CATEGORY
readonly attribute nsIDPtr id
NS_INTERFACE_MAP_END NS_IMPL_CI_INTERFACE_GETTER1(CDatabaseQuery, sbIDatabaseQuery) CDatabaseQuery