[haiku-commits] r41288 - in haiku/trunk/src/add-ons/kernel: file_systems/cdda partitioning_systems/session

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 28 Apr 2011 20:27:12 +0200 (CEST)

Author: axeld
Date: 2011-04-28 20:27:12 +0200 (Thu, 28 Apr 2011)
New Revision: 41288
Changeset: https://dev.haiku-os.org/changeset/41288
Ticket: https://dev.haiku-os.org/ticket/3473

Modified:
   haiku/trunk/src/add-ons/kernel/file_systems/cdda/kernel_interface.cpp
   haiku/trunk/src/add-ons/kernel/partitioning_systems/session/Disc.cpp
   haiku/trunk/src/add-ons/kernel/partitioning_systems/session/Disc.h
   haiku/trunk/src/add-ons/kernel/partitioning_systems/session/session.cpp
Log:
Applied cleaned up patch originally by Ziusudra as part of ticket #3473:
* Changed the session module to create an extra session for existing audio
  tracks.
* Let cdda also recognize "audio partitions" as published by the session module.
* If there is only a single session, the session module now gives file system
  drivers the chance to play with the device directly.


Modified: haiku/trunk/src/add-ons/kernel/file_systems/cdda/kernel_interface.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/cdda/kernel_interface.cpp       
2011-04-28 18:10:42 UTC (rev 41287)
+++ haiku/trunk/src/add-ons/kernel/file_systems/cdda/kernel_interface.cpp       
2011-04-28 18:27:12 UTC (rev 41288)
@@ -544,9 +544,9 @@
 uint32
 count_audio_tracks(scsi_toc_toc* toc)
 {
-       uint32 lastTrack = toc->last_track + 1 - toc->first_track;
+       uint32 trackCount = toc->last_track + 1 - toc->first_track;
        uint32 count = 0;
-       for (uint32 i = 0; i < lastTrack; i++) {
+       for (uint32 i = 0; i < trackCount; i++) {
                if (!is_data_track(toc->tracks[i]))
                        count++;
        }
@@ -1330,8 +1330,10 @@
                        AttrCookieList::Iterator i = fAttrCookies.GetIterator();
                        while (i.HasNext()) {
                                attr_cookie* cookie = i.Next();
-                               if (cookie->current == attribute)
-                                       cookie->current = 
attribute->GetDoublyLinkedListLink()->next;
+                               if (cookie->current == attribute) {
+                                       cookie->current
+                                               = 
attribute->GetDoublyLinkedListLink()->next;
+                               }
                        }
 
                        iterator.Remove();
@@ -1378,11 +1380,41 @@
 
        status_t status = read_table_of_contents(fd, toc, 2048);
 
-       // there has to be at least a single audio track
-       if (status == B_OK && count_audio_tracks(toc) == 0)
-               status = B_BAD_TYPE;
+       // If we succeeded in reading the toc, check the tracks in the
+       // partition, which may not be the whole CD, and if any are audio,
+       // claim the partition.
+       if (status == B_OK) {
+               uint32 trackCount = toc->last_track + (uint32)1 - 
toc->first_track;
+               uint64 sessionStartLBA = partition->offset / 
partition->block_size;
+               uint64 sessionEndLBA    = sessionStartLBA
+                       + (partition->size / partition->block_size);
+               TRACE(("cdda_identify_partition: session at %lld-%lld\n",
+                       sessionStartLBA, sessionEndLBA));
+               status = B_ENTRY_NOT_FOUND;
+               for (uint32 i = 0; i < trackCount; i++) {
+                       // We have to get trackLBA from track.start.time since
+                       // track.start.lba is useless for this.
+                       // This is how session gets it.
+                       uint64 trackLBA
+                               = ((toc->tracks[i].start.time.minute * 
kFramesPerMinute)
+                                       + (toc->tracks[i].start.time.second * 
kFramesPerSecond)
+                                       + toc->tracks[i].start.time.frame - 
150);
+                       if (trackLBA >= sessionStartLBA && trackLBA < 
sessionEndLBA) {
+                               if (is_data_track(toc->tracks[i])) {
+                                       TRACE(("cdda_identify_partition: track 
%ld at %lld is "
+                                               "data\n", i + 1, trackLBA));
+                                       status = B_BAD_TYPE;
+                               } else {
+                                       TRACE(("cdda_identify_partition: track 
%ld at %lld is "
+                                               "audio\n", i + 1, trackLBA));
+                                       status = B_OK;
+                                       break;
+                               }
+                       }
+               }
+       }
 
-       if (status < B_OK) {
+       if (status != B_OK) {
                free(toc);
                return status;
        }
@@ -1740,7 +1772,8 @@
        Volume* volume = (Volume*)_volume->private_volume;
        Inode* inode = (Inode*)_node->private_node;
 
-       TRACE(("cdda_read_stat: vnode %p (0x%Lx), stat %p\n", inode, 
inode->ID(), stat));
+       TRACE(("cdda_read_stat: vnode %p (0x%Lx), stat %p\n", inode, 
inode->ID(),
+               stat));
 
        fill_stat_buffer(volume, inode, NULL, *stat);
 
@@ -1819,7 +1852,8 @@
        Volume* volume = (Volume*)_volume->private_volume;
        Inode* inode = (Inode*)_node->private_node;
 
-       TRACE(("cdda_read_dir: vnode %p, cookie %p, buffer = %p, bufferSize = 
%ld, num = %p\n", _node, _cookie, dirent, bufferSize,_num));
+       TRACE(("cdda_read_dir: vnode %p, cookie %p, buffer = %p, bufferSize = 
%ld,"
+               " num = %p\n", _node, _cookie, buffer, bufferSize,_num));
 
        if ((Inode*)_node->private_node != &volume->RootNode())
                return B_BAD_VALUE;
@@ -1915,7 +1949,7 @@
 {
        dir_cookie* cookie = (dir_cookie*)_cookie;
 
-       TRACE(("cdda_freecookie: entry vnode %p, cookie %p\n", _vnode, cookie));
+       TRACE(("cdda_freecookie: entry vnode %p, cookie %p\n", _node, cookie));
 
        free(cookie);
        return 0;

Modified: haiku/trunk/src/add-ons/kernel/partitioning_systems/session/Disc.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/partitioning_systems/session/Disc.cpp        
2011-04-28 18:10:42 UTC (rev 41287)
+++ haiku/trunk/src/add-ons/kernel/partitioning_systems/session/Disc.cpp        
2011-04-28 18:27:12 UTC (rev 41288)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2009, Haiku, Inc.
+ * Copyright 2003-2011, Haiku, Inc.
  * Distributed under the terms of the MIT license.
  *
  * Authors:
@@ -86,9 +86,9 @@
 
        off_t   start_lba;
        uint8   control;
-               //!< only used to give what are probably useless warnings
+               // Used to check for Yellow/Red Book mixed-mode CDs.
        uint8   adr;
-               //!< only used to give what are probably useless warnings
+               // only used to give what are probably useless warnings
 };
 
 
@@ -548,12 +548,13 @@
                int count;
 
                header = (cdrom_table_of_contents_header*)data;
-               entries = (cdrom_full_table_of_contents_entry*)(data+4);
+               entries = (cdrom_full_table_of_contents_entry*)(data + 4);
                header->length = B_BENDIAN_TO_HOST_INT16(header->length);
 
                count = (header->length - 2)
                        / sizeof(cdrom_full_table_of_contents_entry);
 
+               count = _AdjustForYellowBook(entries, count);
                error = _ParseTableOfContents(entries, count);
 //             Dump();
                if (!error) {
@@ -696,6 +697,92 @@
 }
 
 
+/*! \brief Checks for Yellow Book data tracks in audio sessions and if found
+       inserts them as a new data session.
+*/
+uint32
+Disc::_AdjustForYellowBook(cdrom_full_table_of_contents_entry entries[],
+       uint32 count)
+{
+       uint8 foundCount = 0;
+       uint8 endLBAEntry = 0;
+       uint8 trackTwo = 0;
+
+       // Make sure TOC has only one session and that it is audio.
+       bool sessionIsAudio = true;
+       for (uint32 i = 0; i < count; i++) {
+               if (entries[i].point == 0xa2) {
+                       if ((entries[i].control & kControlDataTrack) != 0) {
+                               sessionIsAudio = false;
+                               break;
+                       }
+                       foundCount++;
+                       endLBAEntry = i;
+               }
+       }
+       if (!sessionIsAudio || foundCount != 1)
+               return count;
+
+       TRACE(("%s: Single audio session, checking for data track\n",
+               kModuleDebugName));
+
+       // See if there are any data tracks.
+       for (uint32 i = 0; i < count; i++) {
+               if (entries[i].point > 0 && entries[i].point < 100
+                       && (entries[i].control & kControlDataTrack) != 0) {
+                       if (entries[i].point == 1) {
+                               // Create a new endLBA point for session one.
+                               entries[count] = entries[endLBAEntry];
+                               entries[count].control = entries[i].control;
+
+                               // Get track two and use it's start as
+                               // the end of our new session.
+                               for (uint8 j = 0; j < count; j++) {
+                                       if (entries[j].point == 2) {
+                                               trackTwo = j;
+                                               break;
+                                       }
+                               }
+                               entries[count].pminutes = 
entries[trackTwo].pminutes;
+                               entries[count].pseconds = 
entries[trackTwo].pseconds;
+                               entries[count].pframes = 
entries[trackTwo].pframes;
+
+                               // Change the other points to session two.
+                               for (uint32 j = 0; j < count; j++) {
+                                       entries[j].session = 2;
+                               }
+                               entries[i].session = 1;
+
+                               count++;
+                               TRACE(("%s: first track is data, adjusted 
TOC\n",
+                                       kModuleDebugName));
+                               break;
+                       } else {
+                               // Change the track to session two.
+                               entries[i].session = 2;
+
+                               // Create a new endLBA point for session two.
+                               entries[count] = entries[endLBAEntry];
+                               entries[count].session = 2;
+                               entries[count].control = entries[i].control;
+
+                               // Use the beginning of the data track as the
+                               // end of the previous session.
+                               entries[endLBAEntry].pminutes = 
entries[i].pminutes;
+                               entries[endLBAEntry].pseconds = 
entries[i].pseconds;
+                               entries[endLBAEntry].pframes = 
entries[i].pframes;
+
+                               count++;
+                               TRACE(("%s: last track is data, adjusted TOC\n",
+                                       kModuleDebugName));
+                               break;
+                       }
+               }
+       }
+       return count;
+}
+
+
 /*! \brief Reads through the given table of contents data and creates an
        unsorted, unverified (i.e. non-error-checked) list of sessions and 
tracks.
 */
@@ -813,7 +900,7 @@
                                        session->track_list.Add(track);
                                } else {
                                        WARN(("%s: warning: illegal point 0x%2x 
found in table of "
-                                               "contents\n", kModuleDebugName, 
entries[i].point));
+                                               "contents\n", kModuleDebugName, 
point));
                                }
                                break;
                }

Modified: haiku/trunk/src/add-ons/kernel/partitioning_systems/session/Disc.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/partitioning_systems/session/Disc.h  
2011-04-28 18:10:42 UTC (rev 41287)
+++ haiku/trunk/src/add-ons/kernel/partitioning_systems/session/Disc.h  
2011-04-28 18:27:12 UTC (rev 41288)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2009, Haiku, Inc.
+ * Copyright 2003-2011, Haiku, Inc.
  * Distributed under the terms of the MIT license.
  *
  * Authors:
@@ -32,27 +32,33 @@
 */
 class Disc {
 public:
-                                                       Disc(int fd);
-                                                       ~Disc();
+                                                               Disc(int fd);
+                                                               ~Disc();
 
-                       status_t                InitCheck();
-                       Session*                GetSession(int32 index);
+                       status_t                        InitCheck();
+                       Session*                        GetSession(int32 index);
 
-                       void                    Dump();
+                       void                            Dump();
 
        // CDs and DVDs are required to have a block size of 2K by
        // the SCSI-3 standard
-       static  const int               kBlockSize = 2048;
+       static  const int                       kBlockSize = 2048;
 
 private:
-                       status_t                _ParseTableOfContents(
-                                                               
cdrom_full_table_of_contents_entry entries[],
-                                                               uint32 count);
-                       void                    _SortAndRemoveDuplicates();
-                       status_t                _CheckForErrorsAndWarnings();
+                       uint32                          _AdjustForYellowBook(
+                                                                       
cdrom_full_table_of_contents_entry
+                                                                               
entries[],
+                                                                       uint32 
count);
+                       status_t                        _ParseTableOfContents(
+                                                                       
cdrom_full_table_of_contents_entry
+                                                                               
entries[],
+                                                                       uint32 
count);
+                       void                            
_SortAndRemoveDuplicates();
+                       status_t                        
_CheckForErrorsAndWarnings();
 
-                       status_t                fInitStatus;
-                       List*                   fSessionList;
+private:
+                       status_t                        fInitStatus;
+                       List*                           fSessionList;
 };
 
 
@@ -61,32 +67,35 @@
 */
 class Session {
 public:
-                                                       ~Session();
+                                                               ~Session();
 
-                       off_t                   Offset() { return fOffset; }
-                       off_t                   Size() { return fSize; }
-                       uint32                  BlockSize() { return 
fBlockSize; }
-                       int32                   Index() { return fIndex; }
-                       uint32                  Flags() { return fFlags; }
-                       const char*             Type() { return fType; }
+                       off_t                           Offset() { return 
fOffset; }
+                       off_t                           Size() { return fSize; }
+                       uint32                          BlockSize() { return 
fBlockSize; }
+                       int32                           Index() { return 
fIndex; }
+                       uint32                          Flags() { return 
fFlags; }
+                       const char*                     Type() { return fType; }
 
 private:
        friend class Disc;
 
-                                                       Session(off_t offset, 
off_t size, uint32 blockSize,
-                                                               int32 index, 
uint32 flags, const char* type);
+                                                               Session(off_t 
offset, off_t size,
+                                                                       uint32 
blockSize, int32 index, uint32 flags,
+                                                                       const 
char* type);
 
-                                                       Session(const Session& 
ref);
-                                                               // not 
implemented
-                       Session&                operator=(const Session& ref);
-                                                               // not 
implemented
+                                                               Session(const 
Session& other);
+                                                                       // not 
implemented
+                       Session&                        operator=(const 
Session& other);
+                                                                       // not 
implemented
 
-                       off_t                   fOffset;
-                       off_t                   fSize;
-                       uint32                  fBlockSize;
-                       int32                   fIndex;
-                       uint32                  fFlags;
-                       char*                   fType;
+private:
+                       off_t                           fOffset;
+                       off_t                           fSize;
+                       uint32                          fBlockSize;
+                       int32                           fIndex;
+                       uint32                          fFlags;
+                       char*                           fType;
 };
 
+
 #endif // _DISC_H

Modified: 
haiku/trunk/src/add-ons/kernel/partitioning_systems/session/session.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/partitioning_systems/session/session.cpp     
2011-04-28 18:10:42 UTC (rev 41287)
+++ haiku/trunk/src/add-ons/kernel/partitioning_systems/session/session.cpp     
2011-04-28 18:27:12 UTC (rev 41288)
@@ -52,12 +52,17 @@
                && geometry.device_type == B_CD) {
                Disc *disc = new(std::nothrow) Disc(fd);
                if (disc != NULL && disc->InitCheck() == B_OK) {
+                       // If we have only a single session then we can let the 
file system
+                       // drivers play directly with the device.
+                       if (disc->GetSession(1) != NULL)
+                               result = 0.9f;
+                       else
+                               result = 0.1f;
                        *cookie = static_cast<void*>(disc);
-                       result = 0.7;
                } else
                        delete disc;
        }
-       PRINT(("returning %ld\n", int32(result * 10000)));
+       PRINT(("returning %g\n", result));
        return result;
 }
 


Other related posts:

  • » [haiku-commits] r41288 - in haiku/trunk/src/add-ons/kernel: file_systems/cdda partitioning_systems/session - axeld